You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gossip.apache.org by ec...@apache.org on 2017/04/13 16:15:54 UTC
[4/7] incubator-gossip git commit: GOSSIP-78 refactor into a
multi-module maven project
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java b/gossip-base/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java
new file mode 100644
index 0000000..8ae783e
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.gossip;
+
+import io.teknek.tunit.TUnit;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.junit.jupiter.api.Test;
+
+@RunWith(JUnitPlatform.class)
+public class TenNodeThreeSeedTest {
+
+ @Test
+ public void test() throws UnknownHostException, InterruptedException, URISyntaxException {
+ abc(30150);
+ }
+
+ @Test
+ public void testAgain() throws UnknownHostException, InterruptedException, URISyntaxException {
+ abc(30100);
+ }
+
+ public void abc(int base) throws InterruptedException, UnknownHostException, URISyntaxException {
+ GossipSettings settings = new GossipSettings(1000, 10000, 1000, 1, 1.6, "exponential");
+ settings.setPersistRingState(false);
+ settings.setPersistDataState(false);
+ String cluster = UUID.randomUUID().toString();
+ int seedNodes = 3;
+ List<Member> startupMembers = new ArrayList<>();
+ for (int i = 1; i < seedNodes+1; ++i) {
+ URI uri = new URI("udp://" + "127.0.0.1" + ":" + (base + i));
+ startupMembers.add(new RemoteMember(cluster, uri, i + ""));
+ }
+ final List<GossipManager> clients = new ArrayList<>();
+ final int clusterMembers = 5;
+ for (int i = 1; i < clusterMembers+1; ++i) {
+ URI uri = new URI("udp://" + "127.0.0.1" + ":" + (base + i));
+ GossipManager gossipService = GossipManagerBuilder.newBuilder()
+ .cluster(cluster)
+ .uri(uri)
+ .id(i + "")
+ .gossipSettings(settings)
+ .gossipMembers(startupMembers)
+ .build();
+ gossipService.init();
+ clients.add(gossipService);
+ }
+ TUnit.assertThat(new Callable<Integer> (){
+ public Integer call() throws Exception {
+ int total = 0;
+ for (int i = 0; i < clusterMembers; ++i) {
+ total += clients.get(i).getLiveMembers().size();
+ }
+ return total;
+ }}).afterWaitingAtMost(40, TimeUnit.SECONDS).isEqualTo(20);
+
+ for (int i = 0; i < clusterMembers; ++i) {
+ int j = i;
+ new Thread(){
+ public void run(){
+ clients.get(j).shutdown();
+ }
+ }.start();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java b/gossip-base/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java
new file mode 100644
index 0000000..3434c17
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.gossip.accrual;
+
+import org.apache.gossip.GossipSettings;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+@RunWith(JUnitPlatform.class)
+public class FailureDetectorTest {
+
+ @FunctionalInterface
+ interface TriConsumer<A, B, C> {
+ void accept(A a, B b, C c);
+ }
+
+ static final Double failureThreshold = new GossipSettings().getConvictThreshold();
+
+ List<Integer> generateTimeList(int begin, int end, int step) {
+ List<Integer> values = new ArrayList<>();
+ Random rand = new Random();
+ for (int i = begin; i < end; i += step) {
+ int delta = (int) ((rand.nextDouble() - 0.5) * step / 2);
+
+ values.add(i + delta);
+ }
+ return values;
+ }
+
+ @Test
+ public void normalDistribution() {
+ FailureDetector fd = new FailureDetector(1, 1000, "normal");
+ List<Integer> values = generateTimeList(0, 10000, 100);
+ Double deltaSum = 0.0;
+ Integer deltaCount = 0;
+ for (int i = 0; i < values.size() - 1; i++) {
+ fd.recordHeartbeat(values.get(i));
+ if (i != 0) {
+ deltaSum += values.get(i) - values.get(i - 1);
+ deltaCount++;
+ }
+ }
+ Integer lastRecorded = values.get(values.size() - 2);
+
+ //after "step" delay we need to be considered UP
+ Assert.assertTrue(fd.computePhiMeasure(values.get(values.size() - 1)) < failureThreshold);
+
+ //if we check phi-measure after mean delay we get value for 0.5 probability(normal distribution)
+ Assert.assertEquals(fd.computePhiMeasure(lastRecorded + Math.round(deltaSum / deltaCount)), -Math.log10(0.5), 0.1);
+ }
+
+ @Test
+ public void checkMinimumSamples() {
+ Integer minimumSamples = 5;
+ FailureDetector fd = new FailureDetector(minimumSamples, 1000, "normal");
+ for (int i = 0; i < minimumSamples + 1; i++) { // +1 because we don't place first heartbeat into structure
+ Assert.assertNull(fd.computePhiMeasure(100));
+ fd.recordHeartbeat(i);
+ }
+ Assert.assertNotNull(fd.computePhiMeasure(100));
+ }
+
+ @Test
+ public void checkMonotonicDead() {
+ final FailureDetector fd = new FailureDetector(5, 1000, "normal");
+ TriConsumer<Integer, Integer, Integer> checkAlive = (begin, end, step) -> {
+ List<Integer> times = generateTimeList(begin, end, step);
+ for (int i = 0; i < times.size(); i++) {
+ Double current = fd.computePhiMeasure(times.get(i));
+ if (current != null) {
+ Assert.assertTrue(current < failureThreshold);
+ }
+ fd.recordHeartbeat(times.get(i));
+ }
+ };
+
+ TriConsumer<Integer, Integer, Integer> checkDeadMonotonic = (begin, end, step) -> {
+ List<Integer> times = generateTimeList(begin, end, step);
+ Double prev = null;
+ for (int i = 0; i < times.size(); i++) {
+ Double current = fd.computePhiMeasure(times.get(i));
+ if (current != null && prev != null) {
+ Assert.assertTrue(current >= prev);
+ }
+ prev = current;
+ }
+ };
+
+ checkAlive.accept(0, 20000, 100);
+ checkDeadMonotonic.accept(20000, 20500, 5);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java b/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java
new file mode 100644
index 0000000..3a134af
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.gossip.crdt;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GrowOnlyCounterTest {
+
+ @Test
+ public void mergeTest() {
+
+ Map<String, Long> node1Counter = new HashMap<>();
+ node1Counter.put("1", 3L);
+ Map<String, Long> node2Counter = new HashMap<>();
+ node2Counter.put("2", 1L);
+ Map<String, Long> node3Counter = new HashMap<>();
+ node3Counter.put("3", 2L);
+
+ GrowOnlyCounter gCounter1 = new GrowOnlyCounter(node1Counter);
+ GrowOnlyCounter gCounter2 = new GrowOnlyCounter(node2Counter);
+ GrowOnlyCounter gCounter3 = new GrowOnlyCounter(node3Counter);
+
+ // After node 2 receive from node 1
+ gCounter2 = gCounter2.merge(gCounter1);
+ Assert.assertEquals(4, (long) gCounter2.value());
+
+ // After node 3 receive from node 1
+ gCounter3 = gCounter3.merge(gCounter1);
+ Assert.assertEquals(5, (long) gCounter3.value());
+
+ // After node 3 receive from node 2
+ gCounter3 = gCounter3.merge(gCounter2);
+ Assert.assertEquals(6, (long) gCounter3.value());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java b/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java
new file mode 100644
index 0000000..d4f12b6
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.gossip.crdt;
+
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GrowOnlySetTest {
+
+ @SuppressWarnings("rawtypes")
+ @Test
+ public void mergeTest(){
+ ConcurrentHashMap<String, Crdt> a = new ConcurrentHashMap<>();
+ GrowOnlySet<String> gset = new GrowOnlySet<>(Arrays.asList("a", "b"));
+ Assert.assertEquals(gset, a.merge("a", gset, new CrdtBiFunctionMerge()));
+ GrowOnlySet<String> over = new GrowOnlySet<>(Arrays.asList("b", "d"));
+ Assert.assertEquals(new GrowOnlySet<>(Arrays.asList("a", "b", "d")),
+ a.merge("a", over, CrdtBiFunctionMerge::applyStatic));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/crdt/OrSetTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/crdt/OrSetTest.java b/gossip-base/src/test/java/org/apache/gossip/crdt/OrSetTest.java
new file mode 100644
index 0000000..b19f221
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/crdt/OrSetTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.gossip.crdt;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class OrSetTest {
+
+ @Test
+ public void atest() {
+ OrSet<Integer> i = new OrSet<>(new OrSet.Builder<Integer>().add(4).add(5).add(6).remove(5));
+ Assert.assertArrayEquals(Arrays.asList(4, 6).toArray(), i.value().toArray());
+ }
+
+ @Test
+ public void mergeTest(){
+ OrSet<Integer> i = new OrSet<>(new OrSet.Builder<Integer>().add(4).add(5).add(6).remove(5));
+ Assert.assertArrayEquals(Arrays.asList(4, 6).toArray(), i.value().toArray());
+ OrSet<Integer> j = new OrSet<>(new OrSet.Builder<Integer>().add(9).add(4).add(5).remove(6));
+ OrSet<Integer> h = i.merge(j);
+ Assert.assertEquals(new OrSet<Integer>(4,6,9,5), h);
+ }
+
+ @Test
+ public void mergeTest2(){
+ OrSet<Integer> i = new OrSet<>(new OrSet.Builder<Integer>().add(5).add(4).remove(4).add(6));
+ Assert.assertEquals(new OrSet<Integer>(5,6), i);
+ SortedSet<Integer> tree = new TreeSet<>();
+ for (Integer in: i.value()){
+ tree.add(in);
+ }
+ TreeSet<Integer> compare = new TreeSet<>();
+ compare.add(5);
+ compare.add(6);
+ Assert.assertEquals(tree, compare);
+ }
+
+ @Test
+ public void mergeTest4() {
+ Assert.assertArrayEquals(new Integer[] {},
+ new OrSet<Integer>(new OrSet.Builder<Integer>().add(1).remove(1)).toArray());
+ }
+
+ @Test
+ public void mergeTest3(){
+ OrSet<Integer> i = new OrSet<>(1);
+ OrSet<Integer> j = new OrSet<>(2);
+ OrSet<Integer> k = new OrSet<>(i.merge(j), new OrSet.Builder<Integer>().remove(1));
+ Assert.assertArrayEquals(new Integer[] { 2 }, i.merge(j).merge(k).toArray());
+ Assert.assertArrayEquals(new Integer[] { 2 }, j.merge(i).merge(k).toArray());
+ Assert.assertArrayEquals(new Integer[] { 2 }, k.merge(i).merge(j).toArray());
+ Assert.assertArrayEquals(new Integer[] { 2 }, k.merge(j).merge(i).toArray());
+ Assert.assertEquals(j , i.merge(j.merge(k)));
+ }
+
+ @Test
+ public void mergeTest9(){
+ OrSet<Integer> i = new OrSet<>(19);
+ OrSet<Integer> j = i.merge(i);
+ Assert.assertEquals(i.value(), j.value());
+ }
+
+ @Test
+ public void serialTest() throws InterruptedException, URISyntaxException, IOException {
+ GossipManager gossipService2 = GossipManagerBuilder.newBuilder()
+ .cluster("a")
+ .uri(new URI("udp://" + "127.0.0.1" + ":" + (29000 + 1)))
+ .id("1")
+ .gossipSettings(new GossipSettings())
+ .build();
+ OrSet<Integer> i = new OrSet<Integer>(new OrSet.Builder<Integer>().add(1).remove(1));
+ String s = gossipService2.getObjectMapper().writeValueAsString(i);
+ @SuppressWarnings("unchecked")
+ OrSet<Integer> back = gossipService2.getObjectMapper().readValue(s, OrSet.class);
+ Assert.assertEquals(back, i);
+ }
+
+ @Test
+ public void mergeTestSame() {
+ OrSet<Integer> i = new OrSet<>(19);
+ OrSet<Integer> j = new OrSet<>(19);
+ OrSet<Integer> k = i.merge(j);
+ Assert.assertEquals(2, k.getElements().get(19).size());
+ OrSet<Integer> y = new OrSet<>(k, new OrSet.Builder<Integer>().remove(19));
+ Assert.assertEquals(2, y.getTombstones().get(19).size());
+ Assert.assertEquals(2, y.getElements().get(19).size());
+ Assert.assertEquals(new OrSet<Integer>().value(), y.value());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/manager/DataReaperTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/manager/DataReaperTest.java b/gossip-base/src/test/java/org/apache/gossip/manager/DataReaperTest.java
new file mode 100644
index 0000000..e328c24
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/manager/DataReaperTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.gossip.manager;
+
+import com.codahale.metrics.MetricRegistry;
+import java.net.URI;
+
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.SharedDataMessage;
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.teknek.tunit.TUnit;
+
+public class DataReaperTest {
+
+ private final MetricRegistry registry = new MetricRegistry();
+ String myId = "4";
+ String key = "key";
+ String value = "a";
+
+ @Test
+ public void testReaperOneShot() {
+ GossipSettings settings = new GossipSettings();
+ settings.setPersistRingState(false);
+ settings.setPersistDataState(false);
+ GossipManager gm = GossipManagerBuilder.newBuilder().cluster("abc").gossipSettings(settings)
+ .id(myId).uri(URI.create("udp://localhost:6000")).registry(registry).build();
+ gm.init();
+ gm.gossipPerNodeData(perNodeDatum(key, value));
+ gm.gossipSharedData(sharedDatum(key, value));
+ assertDataIsAtCorrectValue(gm);
+ gm.getDataReaper().runPerNodeOnce();
+ gm.getDataReaper().runSharedOnce();
+ assertDataIsRemoved(gm);
+ gm.shutdown();
+ }
+
+ private void assertDataIsAtCorrectValue(GossipManager gm){
+ Assert.assertEquals(value, gm.findPerNodeGossipData(myId, key).getPayload());
+ Assert.assertEquals(1, registry.getGauges().get(GossipCoreConstants.PER_NODE_DATA_SIZE).getValue());
+ Assert.assertEquals(value, gm.findSharedGossipData(key).getPayload());
+ Assert.assertEquals(1, registry.getGauges().get(GossipCoreConstants.SHARED_DATA_SIZE).getValue());
+ }
+
+ private void assertDataIsRemoved(GossipManager gm){
+ TUnit.assertThat(() -> gm.findPerNodeGossipData(myId, key)).equals(null);
+ TUnit.assertThat(() -> gm.findSharedGossipData(key)).equals(null);
+ }
+
+ private PerNodeDataMessage perNodeDatum(String key, String value) {
+ PerNodeDataMessage m = new PerNodeDataMessage();
+ m.setExpireAt(System.currentTimeMillis() + 5L);
+ m.setKey(key);
+ m.setPayload(value);
+ m.setTimestamp(System.currentTimeMillis());
+ return m;
+ }
+
+ private SharedDataMessage sharedDatum(String key, String value) {
+ SharedDataMessage m = new SharedDataMessage();
+ m.setExpireAt(System.currentTimeMillis() + 5L);
+ m.setKey(key);
+ m.setPayload(value);
+ m.setTimestamp(System.currentTimeMillis());
+ return m;
+ }
+
+ @Test
+ public void testHigherTimestampWins() {
+ String myId = "4";
+ String key = "key";
+ String value = "a";
+ GossipSettings settings = new GossipSettings();
+ GossipManager gm = GossipManagerBuilder.newBuilder().cluster("abc").gossipSettings(settings)
+ .id(myId).uri(URI.create("udp://localhost:7000")).registry(registry).build();
+ gm.init();
+ PerNodeDataMessage before = perNodeDatum(key, value);
+ PerNodeDataMessage after = perNodeDatum(key, "b");
+ after.setTimestamp(after.getTimestamp() - 1);
+ gm.gossipPerNodeData(before);
+ Assert.assertEquals(value, gm.findPerNodeGossipData(myId, key).getPayload());
+ gm.gossipPerNodeData(after);
+ Assert.assertEquals(value, gm.findPerNodeGossipData(myId, key).getPayload());
+ gm.shutdown();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java b/gossip-base/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java
new file mode 100644
index 0000000..8842643
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.gossip.manager;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.gossip.Member;
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.LocalMember;
+import org.apache.gossip.manager.handlers.DefaultMessageInvoker;
+import org.apache.gossip.manager.handlers.MessageInvoker;
+import org.apache.gossip.manager.handlers.ResponseHandler;
+import org.apache.gossip.manager.handlers.SimpleMessageInvoker;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+import javax.xml.ws.Response;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.expectThrows;
+
+@RunWith(JUnitPlatform.class)
+public class GossipManagerBuilderTest {
+
+ @Test
+ public void idShouldNotBeNull() {
+ expectThrows(IllegalArgumentException.class,() -> {
+ GossipManagerBuilder.newBuilder().cluster("aCluster").build();
+ });
+ }
+
+ @Test
+ public void clusterShouldNotBeNull() {
+ expectThrows(IllegalArgumentException.class,() -> {
+ GossipManagerBuilder.newBuilder().id("id").build();
+ });
+ }
+
+ @Test
+ public void settingsShouldNotBeNull() {
+ expectThrows(IllegalArgumentException.class,() -> {
+ GossipManagerBuilder.newBuilder().id("id").cluster("aCluster").build();
+ });
+ }
+
+ @Test
+ public void createMembersListIfNull() throws URISyntaxException {
+ GossipManager gossipManager = GossipManagerBuilder.newBuilder()
+ .id("id")
+ .cluster("aCluster")
+ .uri(new URI("udp://localhost:2000"))
+ .gossipSettings(new GossipSettings())
+ .gossipMembers(null).registry(new MetricRegistry()).build();
+ assertNotNull(gossipManager.getLiveMembers());
+ }
+
+ @Test
+ public void createDefaultMessageInvokerIfNull() throws URISyntaxException {
+ GossipManager gossipManager = GossipManagerBuilder.newBuilder()
+ .id("id")
+ .cluster("aCluster")
+ .uri(new URI("udp://localhost:2000"))
+ .gossipSettings(new GossipSettings())
+ .messageInvoker(null).registry(new MetricRegistry()).build();
+ assertNotNull(gossipManager.getMessageInvoker());
+ Assert.assertEquals(gossipManager.getMessageInvoker().getClass(), new DefaultMessageInvoker().getClass());
+ }
+
+ @Test
+ public void testMessageInvokerKeeping() throws URISyntaxException {
+ MessageInvoker mi = new SimpleMessageInvoker(Response.class, new ResponseHandler());
+ GossipManager gossipManager = GossipManagerBuilder.newBuilder()
+ .id("id")
+ .cluster("aCluster")
+ .uri(new URI("udp://localhost:2000"))
+ .gossipSettings(new GossipSettings())
+ .messageInvoker(mi).registry(new MetricRegistry()).build();
+ assertNotNull(gossipManager.getMessageInvoker());
+ Assert.assertEquals(gossipManager.getMessageInvoker(), mi);
+ }
+
+ @Test
+ public void useMemberListIfProvided() throws URISyntaxException {
+ LocalMember member = new LocalMember(
+ "aCluster", new URI("udp://localhost:2000"), "aGossipMember",
+ System.nanoTime(), new HashMap<String, String>(), 1000, 1, "exponential");
+ List<Member> memberList = new ArrayList<>();
+ memberList.add(member);
+ GossipManager gossipManager = GossipManagerBuilder.newBuilder()
+ .id("id")
+ .cluster("aCluster")
+ .gossipSettings(new GossipSettings())
+ .uri(new URI("udp://localhost:8000"))
+ .gossipMembers(memberList).registry(new MetricRegistry()).build();
+ assertEquals(1, gossipManager.getDeadMembers().size());
+ assertEquals(member.getId(), gossipManager.getDeadMembers().get(0).getId());
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java b/gossip-base/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java
new file mode 100644
index 0000000..d448b98
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.gossip.manager;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.RemoteMember;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class RingPersistenceTest {
+
+ @Test
+ public void givenThatRingIsPersisted() throws UnknownHostException, InterruptedException, URISyntaxException {
+ GossipSettings settings = new GossipSettings();
+ File f = aGossiperPersists(settings);
+ Assert.assertTrue(f.exists());
+ aNewInstanceGetsRingInfo(settings);
+ f.delete();
+ }
+
+ private File aGossiperPersists(GossipSettings settings) throws UnknownHostException, InterruptedException, URISyntaxException {
+ GossipManager gossipService = GossipManagerBuilder.newBuilder()
+ .cluster("a")
+ .uri(new URI("udp://" + "127.0.0.1" + ":" + (29000 + 1)))
+ .id("1")
+ .gossipSettings(settings)
+ .gossipMembers(
+ Arrays.asList(
+ new RemoteMember("a", new URI("udp://" + "127.0.0.1" + ":" + (29000 + 0)), "0"),
+ new RemoteMember("a", new URI("udp://" + "127.0.0.1" + ":" + (29000 + 2)), "2"))).build();
+ gossipService.getRingState().writeToDisk();
+ return gossipService.getRingState().computeTarget();
+ }
+
+ private void aNewInstanceGetsRingInfo(GossipSettings settings) throws UnknownHostException, InterruptedException, URISyntaxException {
+ GossipManager gossipService2 = GossipManagerBuilder.newBuilder()
+ .cluster("a")
+ .uri(new URI("udp://" + "127.0.0.1" + ":" + (29000 + 1)))
+ .id("1")
+ .gossipSettings(settings).build();
+ Assert.assertEquals(2, gossipService2.getMembers().size());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java b/gossip-base/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java
new file mode 100644
index 0000000..7b17e41
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.gossip.manager;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.SharedDataMessage;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class UserDataPersistenceTest {
+
+ String nodeId = "1";
+
+ private GossipManager sameService() throws URISyntaxException {
+ GossipSettings settings = new GossipSettings();
+ return GossipManagerBuilder.newBuilder()
+ .cluster("a")
+ .uri(new URI("udp://" + "127.0.0.1" + ":" + (29000 + 1)))
+ .id(nodeId)
+ .gossipSettings(settings).build();
+ }
+
+ @Test
+ public void givenThatRingIsPersisted() throws UnknownHostException, InterruptedException, URISyntaxException {
+
+ { //Create a gossip service and force it to persist its user data
+ GossipManager gossipService = sameService();
+ gossipService.init();
+ gossipService.gossipPerNodeData(getToothpick());
+ gossipService.gossipSharedData(getAnotherToothpick());
+ gossipService.getUserDataState().writePerNodeToDisk();
+ gossipService.getUserDataState().writeSharedToDisk();
+ { //read the raw data and confirm
+ ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> l = gossipService.getUserDataState().readPerNodeFromDisk();
+ Assert.assertEquals("red", ((AToothpick) l.get(nodeId).get("a").getPayload()).getColor());
+ }
+ {
+ ConcurrentHashMap<String, SharedDataMessage> l =
+ gossipService.getUserDataState().readSharedDataFromDisk();
+ Assert.assertEquals("blue", ((AToothpick) l.get("a").getPayload()).getColor());
+ }
+ gossipService.shutdown();
+ }
+ { //recreate the service and see that the data is read back in
+ GossipManager gossipService = sameService();
+ gossipService.init();
+ Assert.assertEquals("red", ((AToothpick) gossipService.findPerNodeGossipData(nodeId, "a").getPayload()).getColor());
+ Assert.assertEquals("blue", ((AToothpick) gossipService.findSharedGossipData("a").getPayload()).getColor());
+ File f = gossipService.getUserDataState().computeSharedTarget();
+ File g = gossipService.getUserDataState().computePerNodeTarget();
+ gossipService.shutdown();
+ f.delete();
+ g.delete();
+ }
+ }
+
+ public PerNodeDataMessage getToothpick(){
+ AToothpick a = new AToothpick();
+ a.setColor("red");
+ PerNodeDataMessage d = new PerNodeDataMessage();
+ d.setExpireAt(Long.MAX_VALUE);
+ d.setKey("a");
+ d.setPayload(a);
+ d.setTimestamp(System.currentTimeMillis());
+ return d;
+ }
+
+ public SharedDataMessage getAnotherToothpick(){
+ AToothpick a = new AToothpick();
+ a.setColor("blue");
+ SharedDataMessage d = new SharedDataMessage();
+ d.setExpireAt(Long.MAX_VALUE);
+ d.setKey("a");
+ d.setPayload(a);
+ d.setTimestamp(System.currentTimeMillis());
+ return d;
+ }
+
+ public static class AToothpick {
+ private String color;
+ public AToothpick(){
+
+ }
+ public String getColor() {
+ return color;
+ }
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java b/gossip-base/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java
new file mode 100644
index 0000000..571d7ba
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.gossip.manager.handlers;
+
+import org.apache.gossip.manager.GossipCore;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.model.ActiveGossipMessage;
+import org.apache.gossip.model.Base;
+import org.apache.gossip.udp.UdpSharedDataMessage;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MessageInvokerTest {
+ private class FakeMessage extends Base {
+ public FakeMessage() {
+ }
+ }
+
+ private class FakeMessageData extends Base {
+ public int data;
+
+ public FakeMessageData(int data) {
+ this.data = data;
+ }
+ }
+
+ private class FakeMessageDataHandler implements MessageHandler {
+ public int data;
+
+ public FakeMessageDataHandler() {
+ data = 0;
+ }
+
+ public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+ data = ((FakeMessageData) base).data;
+ }
+ }
+
+ private class FakeMessageHandler implements MessageHandler {
+ public int counter;
+
+ public FakeMessageHandler() {
+ counter = 0;
+ }
+
+ public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+ counter++;
+ }
+ }
+
+ @Test
+ public void testSimpleInvoker() {
+ MessageInvoker mi = new SimpleMessageInvoker(FakeMessage.class, new FakeMessageHandler());
+ Assert.assertTrue(mi.invoke(null, null, new FakeMessage()));
+ Assert.assertFalse(mi.invoke(null, null, new ActiveGossipMessage()));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testSimpleInvokerNullClassConstructor() {
+ new SimpleMessageInvoker(null, new FakeMessageHandler());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testSimpleInvokerNullHandlerConstructor() {
+ new SimpleMessageInvoker(FakeMessage.class, null);
+ }
+
+ @Test
+ public void testCallCountSimpleInvoker() {
+ FakeMessageHandler h = new FakeMessageHandler();
+ MessageInvoker mi = new SimpleMessageInvoker(FakeMessage.class, h);
+ mi.invoke(null, null, new FakeMessage());
+ Assert.assertEquals(1, h.counter);
+ mi.invoke(null, null, new ActiveGossipMessage());
+ Assert.assertEquals(1, h.counter);
+ mi.invoke(null, null, new FakeMessage());
+ Assert.assertEquals(2, h.counter);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void cantAddNullInvoker() {
+ MessageInvokerCombiner mi = new MessageInvokerCombiner();
+ mi.add(null);
+ }
+
+ @Test
+ public void testCombinerClear() {
+ MessageInvokerCombiner mi = new MessageInvokerCombiner();
+ mi.add(new SimpleMessageInvoker(FakeMessage.class, new FakeMessageHandler()));
+ Assert.assertTrue(mi.invoke(null, null, new FakeMessage()));
+
+ mi.clear();
+ Assert.assertFalse(mi.invoke(null, null, new FakeMessage()));
+ }
+
+ @Test
+ public void testMessageInvokerCombiner() {
+ //Empty combiner - false result
+ MessageInvokerCombiner mi = new MessageInvokerCombiner();
+ Assert.assertFalse(mi.invoke(null, null, new Base()));
+
+ FakeMessageHandler h = new FakeMessageHandler();
+ mi.add(new SimpleMessageInvoker(FakeMessage.class, h));
+ mi.add(new SimpleMessageInvoker(FakeMessage.class, h));
+
+ Assert.assertTrue(mi.invoke(null, null, new FakeMessage()));
+ Assert.assertFalse(mi.invoke(null, null, new ActiveGossipMessage()));
+ Assert.assertEquals(2, h.counter);
+
+ //Increase size in runtime. Should be 3 calls: 2+3 = 5
+ mi.add(new SimpleMessageInvoker(FakeMessage.class, h));
+ Assert.assertTrue(mi.invoke(null, null, new FakeMessage()));
+ Assert.assertEquals(5, h.counter);
+ }
+
+ @Test
+ public void testMessageInvokerCombiner2levels() {
+ MessageInvokerCombiner mi = new MessageInvokerCombiner();
+ FakeMessageHandler h = new FakeMessageHandler();
+
+ MessageInvokerCombiner mi1 = new MessageInvokerCombiner();
+ mi1.add(new SimpleMessageInvoker(FakeMessage.class, h));
+ mi1.add(new SimpleMessageInvoker(FakeMessage.class, h));
+
+ MessageInvokerCombiner mi2 = new MessageInvokerCombiner();
+ mi2.add(new SimpleMessageInvoker(FakeMessage.class, h));
+ mi2.add(new SimpleMessageInvoker(FakeMessage.class, h));
+
+ mi.add(mi1);
+ mi.add(mi2);
+
+ Assert.assertTrue(mi.invoke(null, null, new FakeMessage()));
+ Assert.assertEquals(4, h.counter);
+ }
+
+ @Test
+ public void testMessageInvokerCombinerDataShipping() {
+ MessageInvokerCombiner mi = new MessageInvokerCombiner();
+ FakeMessageDataHandler h = new FakeMessageDataHandler();
+ mi.add(new SimpleMessageInvoker(FakeMessageData.class, h));
+
+ Assert.assertTrue(mi.invoke(null, null, new FakeMessageData(101)));
+ Assert.assertEquals(101, h.data);
+ }
+
+ @Test
+ public void testCombiningDefaultInvoker() {
+ MessageInvokerCombiner mi = new MessageInvokerCombiner();
+ mi.add(new DefaultMessageInvoker());
+ mi.add(new SimpleMessageInvoker(FakeMessage.class, new FakeMessageHandler()));
+ //UdpSharedGossipDataMessage with null gossipCore -> exception
+ boolean thrown = false;
+ try {
+ mi.invoke(null, null, new UdpSharedDataMessage());
+ } catch (NullPointerException e) {
+ thrown = true;
+ }
+ Assert.assertTrue(thrown);
+ //DefaultInvoker skips FakeMessage and FakeHandler works ok
+ Assert.assertTrue(mi.invoke(null, null, new FakeMessage()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/resources/log4j.properties b/gossip-base/src/test/resources/log4j.properties
new file mode 100644
index 0000000..e2a60e1
--- /dev/null
+++ b/gossip-base/src/test/resources/log4j.properties
@@ -0,0 +1,20 @@
+# 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.
+
+log4j.rootLogger=INFO,stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
+
+log4j.logger.io.teknek=DEBUG
+log4j.logger.com.google.code.gossip=INFO
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 827f914..f9c7814 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,25 +19,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache</groupId>
- <artifactId>apache</artifactId>
- <version>RELEASE</version>
- </parent>
-
- <groupId>org.apache.gossip</groupId>
- <artifactId>gossip</artifactId>
- <name>gossip</name>
- <version>0.1.3-incubating-SNAPSHOT</version>
- <packaging>jar</packaging>
- <description>A peer to peer cluster discovery service</description>
- <url>http://gossip.incubator.apache.org/</url>
-
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
- <!-- dependecy versions -->
+ <!-- dependency versions -->
<jackson.version>2.8.5</jackson.version>
<metrics.version>3.1.2</metrics.version>
<commons-math.version>1.2</commons-math.version>
@@ -55,6 +41,26 @@
<maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
</properties>
+ <parent>
+ <groupId>org.apache</groupId>
+ <artifactId>apache</artifactId>
+ <version>RELEASE</version>
+ </parent>
+
+ <name>Gossip Parent</name>
+ <groupId>org.apache.gossip</groupId>
+ <artifactId>gossip-parent</artifactId>
+ <version>0.1.3-incubating-SNAPSHOT</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>gossip-base</module>
+ </modules>
+
+ <description>A peer to peer cluster discovery service</description>
+ <url>http://gossip.incubator.apache.org/</url>
+
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
@@ -75,96 +81,23 @@
<url>https://issues.apache.org/jira/browse/GOSSIP</url>
</issueManagement>
- <dependencies>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>${jackson.version}</version>
- </dependency>
- <dependency>
- <groupId>commons-math</groupId>
- <artifactId>commons-math</artifactId>
- <version>${commons-math.version}</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>${jackson.version}</version>
- </dependency>
- <dependency>
- <groupId>io.dropwizard.metrics</groupId>
- <artifactId>metrics-core</artifactId>
- <version>${metrics.version}</version></dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <version>${junit.jupiter.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-engine</artifactId>
- <version>${junit.jupiter.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.vintage</groupId>
- <artifactId>junit-vintage-engine</artifactId>
- <version>${junit.vintage.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.platform</groupId>
- <artifactId>junit-platform-runner</artifactId>
- <version>${junit.platform.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>io.teknek</groupId>
- <artifactId>tunit</artifactId>
- <version>${tunit.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>${log4j.version}</version>
- <type>jar</type>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>javax.jms</groupId>
- <artifactId>jms</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.sun.jdmk</groupId>
- <artifactId>jmxtools</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.sun.jmx</groupId>
- <artifactId>jmxri</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- </dependencies>
-
<build>
<pluginManagement>
<plugins>
- <!-- we need to tweak the maven-release-plugin for GIT -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-release-plugin</artifactId>
- <version>2.5.1</version>
- <configuration>
- <pushChanges>false</pushChanges>
- <localCheckout>true</localCheckout>
- <autoVersionSubmodules>true</autoVersionSubmodules>
+ <!-- we need to tweak the maven-release-plugin for GIT -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.5.1</version>
+ <configuration>
+ <pushChanges>false</pushChanges>
+ <localCheckout>true</localCheckout>
+ <autoVersionSubmodules>true</autoVersionSubmodules>
- <releaseProfiles>distribution</releaseProfiles>
- <preparationGoals>clean install</preparationGoals>
- </configuration>
- </plugin>
+ <releaseProfiles>distribution</releaseProfiles>
+ <preparationGoals>clean install</preparationGoals>
+ </configuration>
+ </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
@@ -197,49 +130,49 @@
</plugins>
</pluginManagement>
<plugins>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.1</version>
- <configuration>
- <source>${java.version}</source>
- <target>${java.version}</target>
- </configuration>
- </plugin>
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.19.1</version>
- <configuration>
- <systemPropertyVariables>
- <java.io.tmpdir>${project.build.directory}</java.io.tmpdir>
- </systemPropertyVariables>
- </configuration>
- <dependencies>
- <dependency>
- <groupId>org.junit.platform</groupId>
- <artifactId>junit-platform-surefire-provider</artifactId>
- <version>${junit.platform.version}</version>
- </dependency>
- </dependencies>
- </plugin>
<plugin>
- <groupId>org.apache.rat</groupId>
- <artifactId>apache-rat-plugin</artifactId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <systemPropertyVariables>
+ <java.io.tmpdir>${project.build.directory}</java.io.tmpdir>
+ </systemPropertyVariables>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-surefire-provider</artifactId>
+ <version>${junit.platform.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
<configuration>
<excludes>
<exclude>README.md</exclude>
<exclude>eclipse_template.xml</exclude>
</excludes>
</configuration>
- <executions>
- <execution>
- <phase>verify</phase>
- <goals>
- <goal>check</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
+ <executions>
+ <execution>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
</build>
<repositories>
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/GossipSettings.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/GossipSettings.java b/src/main/java/org/apache/gossip/GossipSettings.java
deleted file mode 100644
index 6b2bf8b..0000000
--- a/src/main/java/org/apache/gossip/GossipSettings.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.gossip;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * In this object the settings used by the GossipService are held.
- *
- */
-public class GossipSettings {
-
- /** Time between gossip'ing in ms. Default is 1 second. */
- private int gossipInterval = 10;
-
- /** Time between cleanups in ms. Default is 10 seconds. */
- private int cleanupInterval = 5000;
-
- /** the minimum samples needed before reporting a result */
- private int minimumSamples = 5;
-
- /** the number of samples to keep per host */
- private int windowSize = 5000;
-
- /** the threshold for the detector */
- private double convictThreshold = 10;
-
- private String distribution = "normal";
-
- private String activeGossipClass = "org.apache.gossip.manager.SimpleActiveGossipper";
-
- private Map<String,String> activeGossipProperties = new HashMap<>();
-
- private String pathToRingState = "./";
-
- private boolean persistRingState = true;
-
- private String pathToDataState = "./";
-
- private boolean persistDataState = true;
-
- private String pathToKeyStore = "./keys";
-
- private boolean signMessages = false;
-
-
- /**
- * Construct GossipSettings with default settings.
- */
- public GossipSettings() {
- }
-
- /**
- * Construct GossipSettings with given settings.
- *
- * @param gossipInterval
- * The gossip interval in ms.
- * @param cleanupInterval
- * The cleanup interval in ms.
- */
- public GossipSettings(int gossipInterval, int cleanupInterval, int windowSize,
- int minimumSamples, double convictThreshold, String distribution) {
- this.gossipInterval = gossipInterval;
- this.cleanupInterval = cleanupInterval;
- this.windowSize = windowSize;
- this.minimumSamples = minimumSamples;
- this.convictThreshold = convictThreshold;
- this.distribution = distribution;
- }
-
- /**
- * Set the gossip interval. This is the time between a gossip message is send.
- *
- * @param gossipInterval
- * The gossip interval in ms.
- */
- public void setGossipTimeout(int gossipInterval) {
- this.gossipInterval = gossipInterval;
- }
-
- /**
- * Set the cleanup interval. This is the time between the last heartbeat received from a member
- * and when it will be marked as dead.
- *
- * @param cleanupInterval
- * The cleanup interval in ms.
- */
- public void setCleanupInterval(int cleanupInterval) {
- this.cleanupInterval = cleanupInterval;
- }
-
- /**
- * Get the gossip interval.
- *
- * @return The gossip interval in ms.
- */
- public int getGossipInterval() {
- return gossipInterval;
- }
-
- /**
- * Get the clean interval.
- *
- * @return The cleanup interval.
- */
- public int getCleanupInterval() {
- return cleanupInterval;
- }
-
- public int getMinimumSamples() {
- return minimumSamples;
- }
-
- public void setMinimumSamples(int minimumSamples) {
- this.minimumSamples = minimumSamples;
- }
-
- public int getWindowSize() {
- return windowSize;
- }
-
- public void setWindowSize(int windowSize) {
- this.windowSize = windowSize;
- }
-
- public double getConvictThreshold() {
- return convictThreshold;
- }
-
- public void setConvictThreshold(double convictThreshold) {
- this.convictThreshold = convictThreshold;
- }
-
- public void setGossipInterval(int gossipInterval) {
- this.gossipInterval = gossipInterval;
- }
-
- public String getDistribution() {
- return distribution;
- }
-
- public void setDistribution(String distribution) {
- this.distribution = distribution;
- }
-
- public String getActiveGossipClass() {
- return activeGossipClass;
- }
-
- public void setActiveGossipClass(String activeGossipClass) {
- this.activeGossipClass = activeGossipClass;
- }
-
- public Map<String, String> getActiveGossipProperties() {
- return activeGossipProperties;
- }
-
- public void setActiveGossipProperties(Map<String, String> activeGossipProperties) {
- this.activeGossipProperties = activeGossipProperties;
- }
-
- public String getPathToRingState() {
- return pathToRingState;
- }
-
- public void setPathToRingState(String pathToRingState) {
- this.pathToRingState = pathToRingState;
- }
-
- public boolean isPersistRingState() {
- return persistRingState;
- }
-
- public void setPersistRingState(boolean persistRingState) {
- this.persistRingState = persistRingState;
- }
-
- public String getPathToDataState() {
- return pathToDataState;
- }
-
- public void setPathToDataState(String pathToDataState) {
- this.pathToDataState = pathToDataState;
- }
-
- public boolean isPersistDataState() {
- return persistDataState;
- }
-
- public void setPersistDataState(boolean persistDataState) {
- this.persistDataState = persistDataState;
- }
-
- public String getPathToKeyStore() {
- return pathToKeyStore;
- }
-
- public void setPathToKeyStore(String pathToKeyStore) {
- this.pathToKeyStore = pathToKeyStore;
- }
-
- public boolean isSignMessages() {
- return signMessages;
- }
-
- public void setSignMessages(boolean signMessages) {
- this.signMessages = signMessages;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/LocalMember.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/LocalMember.java b/src/main/java/org/apache/gossip/LocalMember.java
deleted file mode 100644
index 450bce5..0000000
--- a/src/main/java/org/apache/gossip/LocalMember.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.gossip;
-
-import java.net.URI;
-import java.util.Map;
-
-import org.apache.gossip.accrual.FailureDetector;
-
-/**
- * This object represent a gossip member with the properties known locally. These objects are stored
- * in the local list of gossip members.
- *
- */
-public class LocalMember extends Member {
- /** The failure detector for this member */
- private transient FailureDetector detector;
-
- /**
- *
- * @param uri
- * The uri of the member
- * @param id
- * id of the node
- * @param heartbeat
- * The current heartbeat
- */
- public LocalMember(String clusterName, URI uri, String id,
- long heartbeat, Map<String,String> properties, int windowSize, int minSamples, String distribution) {
- super(clusterName, uri, id, heartbeat, properties );
- detector = new FailureDetector(minSamples, windowSize, distribution);
- }
-
- protected LocalMember(){
-
- }
-
- public void recordHeartbeat(long now){
- detector.recordHeartbeat(now);
- }
-
- public Double detect(long now) {
- return detector.computePhiMeasure(now);
- }
-
- @Override
- public String toString() {
- Double d = null;
- try {
- d = detect(System.nanoTime());
- } catch (RuntimeException ex) {}
- return "LocalGossipMember [uri=" + uri + ", heartbeat=" + heartbeat + ", clusterName="
- + clusterName + ", id=" + id + ", currentdetect=" + d +" ]";
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/Member.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/Member.java b/src/main/java/org/apache/gossip/Member.java
deleted file mode 100644
index d04a7b6..0000000
--- a/src/main/java/org/apache/gossip/Member.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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.gossip;
-
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.util.Map;
-
-/**
- * A abstract class representing a gossip member.
- *
- */
-public abstract class Member implements Comparable<Member> {
-
-
- protected URI uri;
-
- protected volatile long heartbeat;
-
- protected String clusterName;
-
- /**
- * The purpose of the id field is to be able for nodes to identify themselves beyond their
- * host/port. For example an application might generate a persistent id so if they rejoin the
- * cluster at a different host and port we are aware it is the same node.
- */
- protected String id;
-
- /* properties provided at startup time */
- protected Map<String,String> properties;
-
- /**
- * Constructor.
- *
- * @param clusterName
- * The name of the cluster
- * @param uri
- * A URI object containing IP/hostname and port
- * @param heartbeat
- * The current heartbeat
- * @param id
- * An id that may be replaced after contact
- */
- public Member(String clusterName, URI uri, String id, long heartbeat, Map<String,String> properties) {
- this.clusterName = clusterName;
- this.id = id;
- this.heartbeat = heartbeat;
- this.uri = uri;
- this.properties = properties;
- }
-
- protected Member(){}
- /**
- * Get the name of the cluster the member belongs to.
- *
- * @return The cluster name
- */
- public String getClusterName() {
- return clusterName;
- }
-
-
- /**
- * @return The member address in the form IP/host:port Similar to the toString in
- * {@link InetSocketAddress}
- */
- public String computeAddress() {
- return uri.getHost() + ":" + uri.getPort();
- }
-
- /**
- * Get the heartbeat of this gossip member.
- *
- * @return The current heartbeat.
- */
- public long getHeartbeat() {
- return heartbeat;
- }
-
- /**
- * Set the heartbeat of this gossip member.
- *
- * @param heartbeat
- * The new heartbeat.
- */
- public void setHeartbeat(long heartbeat) {
- this.heartbeat = heartbeat;
- }
-
- public String getId() {
- return id;
- }
-
- public void setId(String _id) {
- this.id = _id;
- }
-
- public Map<String, String> getProperties() {
- return properties;
- }
-
- public void setProperties(Map<String, String> properties) {
- this.properties = properties;
- }
-
- public String toString() {
- return "Member [address=" + computeAddress() + ", id=" + id + ", heartbeat=" + heartbeat + "]";
- }
-
- /**
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- String address = computeAddress();
- result = prime * result + ((address == null) ? 0 : address.hashCode()) + (clusterName == null ? 0
- : clusterName.hashCode());
- return result;
- }
-
- public URI getUri() {
- return uri;
- }
-
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- System.err.println("equals(): obj is null.");
- return false;
- }
- if (!(obj instanceof Member)) {
- System.err.println("equals(): obj is not of type GossipMember.");
- return false;
- }
- // The object is the same of they both have the same address (hostname and port).
- return computeAddress().equals(((LocalMember) obj).computeAddress())
- && getClusterName().equals(((LocalMember) obj).getClusterName());
- }
-
- public int compareTo(Member other) {
- return this.computeAddress().compareTo(other.computeAddress());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/RemoteMember.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/RemoteMember.java b/src/main/java/org/apache/gossip/RemoteMember.java
deleted file mode 100644
index 6b42da2..0000000
--- a/src/main/java/org/apache/gossip/RemoteMember.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.gossip;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The object represents a gossip member with the properties as received from a remote gossip
- * member.
- *
- */
-public class RemoteMember extends Member {
-
- /**
- * Constructor.
- *
- * @param uri
- * A URI object containing IP/hostname and port
- * @param heartbeat
- * The current heartbeat
- */
- public RemoteMember(String clusterName, URI uri, String id, long heartbeat, Map<String,String> properties) {
- super(clusterName, uri, id, heartbeat, properties);
- }
-
- public RemoteMember(String clusterName, URI uri, String id) {
- super(clusterName, uri, id, System.nanoTime(), new HashMap<String,String>());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/StartupSettings.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/StartupSettings.java b/src/main/java/org/apache/gossip/StartupSettings.java
deleted file mode 100644
index 17eaaf2..0000000
--- a/src/main/java/org/apache/gossip/StartupSettings.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.gossip;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.log4j.Logger;
-
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/**
- * This object represents the settings used when starting the gossip service.
- *
- */
-public class StartupSettings {
- private static final Logger log = Logger.getLogger(StartupSettings.class);
-
- /** The id to use fo the service */
- private String id;
-
- private URI uri;
-
- private String cluster;
-
- /** The gossip settings used at startup. */
- private final GossipSettings gossipSettings;
-
- /** The list with gossip members to start with. */
- private final List<Member> gossipMembers;
-
- /**
- * Constructor.
- *
- * @param id
- * The id to be used for this service
- * @param uri
- * A URI object containing IP/hostname and port
- * @param logLevel
- * unused
- */
- public StartupSettings(String id, URI uri, int logLevel, String cluster) {
- this(id, uri, new GossipSettings(), cluster);
- }
-
- public URI getUri() {
- return uri;
- }
-
- public void setUri(URI uri) {
- this.uri = uri;
- }
-
- /**
- * Constructor.
- *
- * @param id
- * The id to be used for this service
- * @param uri
- * A URI object containing IP/hostname and port
- */
- public StartupSettings(String id, URI uri, GossipSettings gossipSettings, String cluster) {
- this.id = id;
- this.uri = uri;
- this.gossipSettings = gossipSettings;
- this.setCluster(cluster);
- gossipMembers = new ArrayList<>();
- }
-
- public void setCluster(String cluster) {
- this.cluster = cluster;
- }
-
- public String getCluster() {
- return cluster;
- }
-
- /**
- * Set the id to be used for this service.
- *
- * @param id
- * The id for this service.
- */
- public void setId(String id) {
- this.id = id;
- }
-
- /**
- * Get the id for this service.
- *
- * @return the service's id.
- */
- public String getId() {
- return id;
- }
-
- /**
- * Get the GossipSettings.
- *
- * @return The GossipSettings object.
- */
- public GossipSettings getGossipSettings() {
- return gossipSettings;
- }
-
- /**
- * Add a gossip member to the list of members to start with.
- *
- * @param member
- * The member to add.
- */
- public void addGossipMember(Member member) {
- gossipMembers.add(member);
- }
-
- /**
- * Get the list with gossip members.
- *
- * @return The gossip members.
- */
- public List<Member> getGossipMembers() {
- return gossipMembers;
- }
-
- /**
- * Parse the settings for the gossip service from a JSON file.
- *
- * @param jsonFile
- * The file object which refers to the JSON config file.
- * @return The StartupSettings object with the settings from the config file.
- * @throws FileNotFoundException
- * Thrown when the file cannot be found.
- * @throws IOException
- * Thrown when reading the file gives problems.
- * @throws URISyntaxException
- */
- public static StartupSettings fromJSONFile(File jsonFile) throws
- FileNotFoundException, IOException, URISyntaxException {
- ObjectMapper om = new ObjectMapper();
- JsonNode root = om.readTree(jsonFile);
- JsonNode jsonObject = root.get(0);
- String uri = jsonObject.get("uri").textValue();
- String id = jsonObject.get("id").textValue();
- Map<String,String> properties = new HashMap<String,String>();
- JsonNode n = jsonObject.get("properties");
- Iterator<Entry<String, JsonNode>> l = n.fields();
- while (l.hasNext()){
- Entry<String, JsonNode> i = l.next();
- properties.put(i.getKey(), i.getValue().asText());
- }
- //TODO constants as defaults?
- int gossipInterval = jsonObject.get("gossip_interval").intValue();
- int cleanupInterval = jsonObject.get("cleanup_interval").intValue();
- int windowSize = jsonObject.get("window_size").intValue();
- int minSamples = jsonObject.get("minimum_samples").intValue();
- double convictThreshold = jsonObject.get("convict_threshold").asDouble();
- String cluster = jsonObject.get("cluster").textValue();
- String distribution = jsonObject.get("distribution").textValue();
- if (cluster == null){
- throw new IllegalArgumentException("cluster was null. It is required");
- }
- URI uri2 = new URI(uri);
- StartupSettings settings = new StartupSettings(id, uri2,
- new GossipSettings(gossipInterval, cleanupInterval, windowSize,
- minSamples, convictThreshold, distribution), cluster);
- String configMembersDetails = "Config-members [";
- JsonNode membersJSON = jsonObject.get("members");
- Iterator<JsonNode> it = membersJSON.iterator();
- while (it.hasNext()){
- JsonNode child = it.next();
- URI uri3 = new URI(child.get("uri").textValue());
- RemoteMember member = new RemoteMember(child.get("cluster").asText(),
- uri3, "", 0, new HashMap<String,String>());
- settings.addGossipMember(member);
- configMembersDetails += member.computeAddress();
- configMembersDetails += ", ";
- }
- log.info(configMembersDetails + "]");
- return settings;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/accrual/FailureDetector.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/accrual/FailureDetector.java b/src/main/java/org/apache/gossip/accrual/FailureDetector.java
deleted file mode 100644
index 5abd5c6..0000000
--- a/src/main/java/org/apache/gossip/accrual/FailureDetector.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.gossip.accrual;
-
-import org.apache.commons.math.MathException;
-import org.apache.commons.math.distribution.ExponentialDistributionImpl;
-import org.apache.commons.math.distribution.NormalDistributionImpl;
-import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
-import org.apache.log4j.Logger;
-
-public class FailureDetector {
-
- public static final Logger LOGGER = Logger.getLogger(FailureDetector.class);
- private final DescriptiveStatistics descriptiveStatistics;
- private final long minimumSamples;
- private volatile long latestHeartbeatMs = -1;
- private final String distribution;
-
- public FailureDetector(long minimumSamples, int windowSize, String distribution) {
- descriptiveStatistics = new DescriptiveStatistics(windowSize);
- this.minimumSamples = minimumSamples;
- this.distribution = distribution;
- }
-
- /**
- * Updates the statistics based on the delta between the last
- * heartbeat and supplied time
- *
- * @param now the time of the heartbeat in milliseconds
- */
- public synchronized void recordHeartbeat(long now) {
- if (now <= latestHeartbeatMs) {
- return;
- }
- if (latestHeartbeatMs != -1) {
- descriptiveStatistics.addValue(now - latestHeartbeatMs);
- }
- latestHeartbeatMs = now;
- }
-
- public synchronized Double computePhiMeasure(long now) {
- if (latestHeartbeatMs == -1 || descriptiveStatistics.getN() < minimumSamples) {
- return null;
- }
- long delta = now - latestHeartbeatMs;
- try {
- double probability;
- if (distribution.equals("normal")) {
- double standardDeviation = descriptiveStatistics.getStandardDeviation();
- standardDeviation = standardDeviation < 0.1 ? 0.1 : standardDeviation;
- probability = new NormalDistributionImpl(descriptiveStatistics.getMean(), standardDeviation).cumulativeProbability(delta);
- } else {
- probability = new ExponentialDistributionImpl(descriptiveStatistics.getMean()).cumulativeProbability(delta);
- }
- final double eps = 1e-12;
- if (1 - probability < eps) {
- probability = 1.0;
- }
- return -1.0d * Math.log10(1.0d - probability);
- } catch (MathException | IllegalArgumentException e) {
- LOGGER.debug(e);
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/Crdt.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/Crdt.java b/src/main/java/org/apache/gossip/crdt/Crdt.java
deleted file mode 100644
index 8edfa8c..0000000
--- a/src/main/java/org/apache/gossip/crdt/Crdt.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.gossip.crdt;
-/**
- *
- * Immutable type
- *
- * @param <SetType>
- * @param <MergeReturnType>
- */
-public interface Crdt<SetType, MergeReturnType extends Crdt<SetType, MergeReturnType>> {
-
-
- MergeReturnType merge(MergeReturnType other);
- SetType value();
- /**
- * Called to self optimize. Some CRDTs may use some mechanism to clean up be
- * removing obsolete data outside the scope of merging. IE this could clean up
- * temporal values, old copies etc.
- * @return the Crdt structure optimized
- */
- MergeReturnType optimize();
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java b/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java
deleted file mode 100644
index 1ac7a30..0000000
--- a/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.gossip.crdt;
-
-import java.util.function.BiFunction;
-
-@SuppressWarnings("rawtypes")
-public class CrdtBiFunctionMerge implements BiFunction<Crdt,Crdt,Crdt> {
-
- @SuppressWarnings("unchecked")
- @Override
- public Crdt apply(Crdt t, Crdt u) {
- if (t == null && u == null){
- return null;
- } else if (t == null){
- return u;
- } else if (u == null){
- return t;
- }
- if (! u.getClass().equals(t.getClass())){
- throw new IllegalArgumentException( "Can not merge " + t.getClass() + " "+ u.getClass());
- }
- return t.merge(u);
- }
-
- @SuppressWarnings("unchecked")
- public static Crdt applyStatic(Crdt t, Crdt u){
- if (t == null && u == null){
- return null;
- } else if (t == null){
- return u;
- } else if (u == null){
- return t;
- }
- if (! u.getClass().equals(t.getClass())){
- throw new IllegalArgumentException( "Can not merge " + t.getClass() + " "+ u.getClass());
- }
- return t.merge(u);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/CrdtCounter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/CrdtCounter.java b/src/main/java/org/apache/gossip/crdt/CrdtCounter.java
deleted file mode 100644
index cdc9445..0000000
--- a/src/main/java/org/apache/gossip/crdt/CrdtCounter.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.gossip.crdt;
-
-public interface CrdtCounter<ValueType extends Number, R extends CrdtCounter<ValueType, R>>
- extends Crdt<ValueType, R> {
-
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/CrdtModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/CrdtModule.java b/src/main/java/org/apache/gossip/crdt/CrdtModule.java
deleted file mode 100644
index cfb3f47..0000000
--- a/src/main/java/org/apache/gossip/crdt/CrdtModule.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.gossip.crdt;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.core.Version;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-abstract class OrSetMixin<E> {
- @JsonCreator
- OrSetMixin(@JsonProperty("elements") Map<E, Set<UUID>> w, @JsonProperty("tombstones") Map<E, Set<UUID>> h) { }
- @JsonProperty("elements") abstract Map<E, Set<UUID>> getElements();
- @JsonProperty("tombstones") abstract Map<E, Set<UUID>> getTombstones();
- @JsonIgnore abstract boolean isEmpty();
-}
-
-abstract class GrowOnlySetMixin<E>{
- @JsonCreator
- GrowOnlySetMixin(@JsonProperty("elements") Set<E> elements){ }
- @JsonProperty("elements") abstract Set<E> getElements();
- @JsonIgnore abstract boolean isEmpty();
-}
-
-abstract class GrowOnlyCounterMixin {
- @JsonCreator
- GrowOnlyCounterMixin(@JsonProperty("counters") Map<String, Long> counters) { }
- @JsonProperty("counters") abstract Map<String, Long> getCounters();
-}
-
-//If anyone wants to take a stab at this. please have at it
-//https://github.com/FasterXML/jackson-datatype-guava/blob/master/src/main/java/com/fasterxml/jackson/datatype/guava/ser/MultimapSerializer.java
-public class CrdtModule extends SimpleModule {
-
- private static final long serialVersionUID = 6134836523275023418L;
-
- public CrdtModule() {
- super("CrdtModule", new Version(0, 0, 0, "0.0.0", "org.apache.gossip", "gossip"));
- }
-
- @Override
- public void setupModule(SetupContext context) {
- context.setMixInAnnotations(OrSet.class, OrSetMixin.class);
- context.setMixInAnnotations(GrowOnlySet.class, GrowOnlySetMixin.class);
- context.setMixInAnnotations(GrowOnlyCounter.class, GrowOnlyCounterMixin.class);
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/CrdtSet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/CrdtSet.java b/src/main/java/org/apache/gossip/crdt/CrdtSet.java
deleted file mode 100644
index 21b41da..0000000
--- a/src/main/java/org/apache/gossip/crdt/CrdtSet.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.gossip.crdt;
-
-import java.util.Set;
-
-public interface CrdtSet<ElementType, SetType extends Set<ElementType>, R extends CrdtSet<ElementType, SetType, R>>
-extends Crdt<SetType, R> {
-
-}
-