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> { - -} -
