Merge branch 'CURATOR-275' of github.com:joelittlejohn/curator into CURATOR-275
authorrandgalt <randgalt@apache.org>
Tue, 24 Jan 2017 01:53:00 +0000 (20:53 -0500)
committerrandgalt <randgalt@apache.org>
Tue, 24 Jan 2017 01:53:00 +0000 (20:53 -0500)
curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstance.java
curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java
curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/EnabledInstanceFilter.java [new file with mode: 0644]
curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/ServiceProviderImpl.java
curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java
curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestServiceProvider.java [new file with mode: 0644]

index 939e708..820e92c 100644 (file)
@@ -42,6 +42,7 @@ public class ServiceInstance<T>
     private final long          registrationTimeUTC;
     private final ServiceType   serviceType;
     private final UriSpec       uriSpec;
+    private final boolean       enabled;
 
     /**
      * Return a new builder. The {@link #address} is set to the ip of the first
@@ -75,7 +76,7 @@ public class ServiceInstance<T>
      * @param serviceType type of the service
      * @param uriSpec the uri spec or null
      */
-    public ServiceInstance(String name, String id, String address, Integer port, Integer sslPort, T payload, long registrationTimeUTC, ServiceType serviceType, UriSpec uriSpec)
+    public ServiceInstance(String name, String id, String address, Integer port, Integer sslPort, T payload, long registrationTimeUTC, ServiceType serviceType, UriSpec uriSpec, boolean enabled)
     {
         name = Preconditions.checkNotNull(name, "name cannot be null");
         id = Preconditions.checkNotNull(id, "id cannot be null");
@@ -89,6 +90,7 @@ public class ServiceInstance<T>
         this.sslPort = sslPort;
         this.payload = payload;
         this.registrationTimeUTC = registrationTimeUTC;
+        this.enabled = enabled;
     }
 
     /**
@@ -96,7 +98,7 @@ public class ServiceInstance<T>
      */
     ServiceInstance()
     {
-        this("", "", null, null, null, null, 0, ServiceType.DYNAMIC, null);
+        this("", "", null, null, null, null, 0, ServiceType.DYNAMIC, null, true);
     }
 
     public String getName()
@@ -145,6 +147,11 @@ public class ServiceInstance<T>
         return uriSpec;
     }
 
+    public boolean isEnabled()
+    {
+        return enabled;
+    }
+
     public String buildUriSpec()
     {
         return buildUriSpec(Maps.<String, Object>newHashMap());
@@ -206,6 +213,10 @@ public class ServiceInstance<T>
         {
             return false;
         }
+        if ( enabled != that.enabled )
+        {
+            return false;
+        }
 
         return true;
     }
@@ -222,6 +233,7 @@ public class ServiceInstance<T>
         result = 31 * result + (int)(registrationTimeUTC ^ (registrationTimeUTC >>> 32));
         result = 31 * result + (serviceType != null ? serviceType.hashCode() : 0);
         result = 31 * result + (uriSpec != null ? uriSpec.hashCode() : 0);
+        result = 31 * result + (enabled ? 1231 : 1237);
         return result;
     }
 
@@ -238,6 +250,7 @@ public class ServiceInstance<T>
             ", registrationTimeUTC=" + registrationTimeUTC +
             ", serviceType=" + serviceType +
             ", uriSpec=" + uriSpec +
+            ", enabled=" + enabled +
             '}';
     }
 }
index 4365cd6..c2ea40e 100644 (file)
@@ -41,6 +41,7 @@ public class ServiceInstanceBuilder<T>
     private long registrationTimeUTC;
     private ServiceType serviceType = ServiceType.DYNAMIC;
     private UriSpec uriSpec;
+    private boolean enabled = true;
 
     private static final AtomicReference<LocalIpFilter> localIpFilter = new AtomicReference<LocalIpFilter>
     (
@@ -85,7 +86,7 @@ public class ServiceInstanceBuilder<T>
      */
     public ServiceInstance<T> build()
     {
-        return new ServiceInstance<T>(name, id, address, port, sslPort, payload, registrationTimeUTC, serviceType, uriSpec);
+        return new ServiceInstance<T>(name, id, address, port, sslPort, payload, registrationTimeUTC, serviceType, uriSpec, enabled);
     }
 
     public ServiceInstanceBuilder<T> name(String name)
@@ -142,6 +143,12 @@ public class ServiceInstanceBuilder<T>
         return this;
     }
 
+    public ServiceInstanceBuilder<T> enabled(boolean enabled)
+    {
+        this.enabled = enabled;
+        return this;
+    }
+
     /**
      * based on http://pastebin.com/5X073pUc
      * <p>
diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/EnabledInstanceFilter.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/EnabledInstanceFilter.java
new file mode 100644 (file)
index 0000000..d153653
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * 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.curator.x.discovery.details;
+
+import org.apache.curator.x.discovery.InstanceFilter;
+import org.apache.curator.x.discovery.ServiceInstance;
+
+public class EnabledInstanceFilter<T> implements InstanceFilter<T>
+{
+
+    @Override
+    public boolean apply(ServiceInstance<T> instance)
+    {
+        return instance.isEnabled();
+    }
+
+}
index 5c63836..4cbd126 100644 (file)
@@ -53,6 +53,7 @@ public class ServiceProviderImpl<T> implements ServiceProvider<T>
 
         ArrayList<InstanceFilter<T>> localFilters = Lists.newArrayList(filters);
         localFilters.add(downInstanceManager);
+        localFilters.add(new EnabledInstanceFilter<T>());
         instanceProvider = new FilteredInstanceProvider<T>(cache, localFilters);
     }
 
index 8417710..f17919d 100644 (file)
@@ -32,8 +32,8 @@ public class TestJsonInstanceSerializer
     @Test
     public void     testBasic() throws Exception
     {
-        JsonInstanceSerializer<String> serializer = new JsonInstanceSerializer<String>(String.class);
-        ServiceInstance<String>         instance = new ServiceInstance<String>("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"));
+        JsonInstanceSerializer<String>  serializer = new JsonInstanceSerializer<String>(String.class);
+        ServiceInstance<String>         instance = new ServiceInstance<String>("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true);
         byte[]                          bytes = serializer.serialize(instance);
 
         ServiceInstance<String>         rhs = serializer.deserialize(bytes);
@@ -45,6 +45,7 @@ public class TestJsonInstanceSerializer
         Assert.assertEquals(instance.getPort(), rhs.getPort());
         Assert.assertEquals(instance.getSslPort(), rhs.getSslPort());
         Assert.assertEquals(instance.getUriSpec(), rhs.getUriSpec());
+        Assert.assertEquals(instance.isEnabled(), rhs.isEnabled());
     }
 
     @Test
@@ -53,7 +54,7 @@ public class TestJsonInstanceSerializer
         JsonInstanceSerializer<String>  stringSerializer = new JsonInstanceSerializer<String>(String.class);
         JsonInstanceSerializer<Double>  doubleSerializer = new JsonInstanceSerializer<Double>(Double.class);
 
-        byte[]                          bytes = stringSerializer.serialize(new ServiceInstance<String>("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}")));
+        byte[]                          bytes = stringSerializer.serialize(new ServiceInstance<String>("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true));
         try
         {
             doubleSerializer.deserialize(bytes);
@@ -69,7 +70,7 @@ public class TestJsonInstanceSerializer
     public void     testNoPayload() throws Exception
     {
         JsonInstanceSerializer<Void>    serializer = new JsonInstanceSerializer<Void>(Void.class);
-        ServiceInstance<Void>           instance = new ServiceInstance<Void>("name", "id", "address", 10, 20, null, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"));
+        ServiceInstance<Void>           instance = new ServiceInstance<Void>("name", "id", "address", 10, 20, null, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true);
         byte[]                          bytes = serializer.serialize(instance);
 
         ServiceInstance<Void>           rhs = serializer.deserialize(bytes);
@@ -81,6 +82,17 @@ public class TestJsonInstanceSerializer
         Assert.assertEquals(instance.getPort(), rhs.getPort());
         Assert.assertEquals(instance.getSslPort(), rhs.getSslPort());
         Assert.assertEquals(instance.getUriSpec(), rhs.getUriSpec());
+        Assert.assertEquals(instance.isEnabled(), rhs.isEnabled());
+    }
+
+    @Test
+    public void     testNoEnabledState() throws Exception
+    {
+        JsonInstanceSerializer<Void>    serializer = new JsonInstanceSerializer<Void>(Void.class);
+        byte[]                          bytes = "{}".getBytes("utf-8");
+
+        ServiceInstance<Void>           instance = serializer.deserialize(bytes);
+        Assert.assertTrue(instance.isEnabled(), "Instance that has no 'enabled' should be assumed enabled");
     }
 
     @Test
@@ -90,8 +102,8 @@ public class TestJsonInstanceSerializer
         List<String> payload = new ArrayList<String>();
         payload.add("Test value 1");
         payload.add("Test value 2");
-        ServiceInstance<Object>           instance = new ServiceInstance<Object>("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"));
-        byte[]                          bytes = serializer.serialize(instance);
+        ServiceInstance<Object>           instance = new ServiceInstance<Object>("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false);
+        byte[]                            bytes = serializer.serialize(instance);
 
         ServiceInstance<Object>           rhs = serializer.deserialize(bytes);
         Assert.assertEquals(instance, rhs);
@@ -102,6 +114,7 @@ public class TestJsonInstanceSerializer
         Assert.assertEquals(instance.getPort(), rhs.getPort());
         Assert.assertEquals(instance.getSslPort(), rhs.getSslPort());
         Assert.assertEquals(instance.getUriSpec(), rhs.getUriSpec());
+        Assert.assertEquals(instance.isEnabled(), rhs.isEnabled());
     }
 
 
@@ -112,8 +125,8 @@ public class TestJsonInstanceSerializer
         Map<String,String> payload = new HashMap<String,String>();
         payload.put("1", "Test value 1");
         payload.put("2", "Test value 2");
-        ServiceInstance<Object>           instance = new ServiceInstance<Object>("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"));
-        byte[]                          bytes = serializer.serialize(instance);
+        ServiceInstance<Object>           instance = new ServiceInstance<Object>("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false);
+        byte[]                            bytes = serializer.serialize(instance);
 
         ServiceInstance<Object>           rhs = serializer.deserialize(bytes);
         Assert.assertEquals(instance, rhs);
@@ -124,6 +137,7 @@ public class TestJsonInstanceSerializer
         Assert.assertEquals(instance.getPort(), rhs.getPort());
         Assert.assertEquals(instance.getSslPort(), rhs.getSslPort());
         Assert.assertEquals(instance.getUriSpec(), rhs.getUriSpec());
+        Assert.assertEquals(instance.isEnabled(), rhs.isEnabled());
     }
 
     @Test
@@ -132,8 +146,8 @@ public class TestJsonInstanceSerializer
         JsonInstanceSerializer<Payload>    serializer = new JsonInstanceSerializer<Payload>(Payload.class);
         Payload payload = new Payload();
         payload.setVal("Test value");
-        ServiceInstance<Payload>           instance = new ServiceInstance<Payload>("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"));
-        byte[]                          bytes = serializer.serialize(instance);
+        ServiceInstance<Payload>           instance = new ServiceInstance<Payload>("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true);
+        byte[]                             bytes = serializer.serialize(instance);
 
         ServiceInstance<Payload>           rhs = serializer.deserialize(bytes);
         Assert.assertEquals(instance, rhs);
@@ -144,6 +158,7 @@ public class TestJsonInstanceSerializer
         Assert.assertEquals(instance.getPort(), rhs.getPort());
         Assert.assertEquals(instance.getSslPort(), rhs.getSslPort());
         Assert.assertEquals(instance.getUriSpec(), rhs.getUriSpec());
+        Assert.assertEquals(instance.isEnabled(), rhs.isEnabled());
     }
 
     public static class Payload {
diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestServiceProvider.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestServiceProvider.java
new file mode 100644 (file)
index 0000000..fae7266
--- /dev/null
@@ -0,0 +1,109 @@
+/**
+ * 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.curator.x.discovery.details;
+
+import java.io.Closeable;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.curator.x.discovery.ServiceDiscovery;
+import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
+import org.apache.curator.x.discovery.ServiceInstance;
+import org.apache.curator.x.discovery.ServiceProvider;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+
+public class TestServiceProvider extends BaseClassForTests
+{
+
+    @Test
+    public void testBasic() throws Exception
+    {
+        List<Closeable> closeables = Lists.newArrayList();
+        try
+        {
+            CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+            closeables.add(client);
+            client.start();
+
+            ServiceInstance<String> instance = ServiceInstance.<String>builder().payload("thing").name("test").port(10064).build();
+            ServiceDiscovery<String> discovery = ServiceDiscoveryBuilder.builder(String.class).basePath("/test").client(client).thisInstance(instance).build();
+            closeables.add(discovery);
+            discovery.start();
+
+            ServiceProvider<String> provider = discovery.serviceProviderBuilder().serviceName("test").build();
+            closeables.add(provider);
+            provider.start();
+
+            Assert.assertEquals(provider.getInstance(), instance);
+
+            List<ServiceInstance<String>> list = Lists.newArrayList();
+            list.add(instance);
+            Assert.assertEquals(provider.getAllInstances(), list);
+        }
+        finally
+        {
+            Collections.reverse(closeables);
+            for ( Closeable c : closeables )
+            {
+                CloseableUtils.closeQuietly(c);
+            }
+        }
+    }
+
+    @Test
+    public void testDisabledInstance() throws Exception
+    {
+        List<Closeable> closeables = Lists.newArrayList();
+        try
+        {
+            CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+            closeables.add(client);
+            client.start();
+
+            ServiceInstance<String> instance = ServiceInstance.<String>builder().payload("thing").name("test").port(10064).enabled(false).build();
+            ServiceDiscovery<String> discovery = ServiceDiscoveryBuilder.builder(String.class).basePath("/test").client(client).thisInstance(instance).build();
+            closeables.add(discovery);
+            discovery.start();
+
+            ServiceProvider<String> provider = discovery.serviceProviderBuilder().serviceName("test").build();
+            closeables.add(provider);
+            provider.start();
+
+            Assert.assertEquals(provider.getInstance(), null);
+            Assert.assertTrue(provider.getAllInstances().isEmpty(), "Disabled instance still appears available via service provider");
+        }
+        finally
+        {
+            Collections.reverse(closeables);
+            for ( Closeable c : closeables )
+            {
+                CloseableUtils.closeQuietly(c);
+            }
+        }
+    }
+
+}