gossip-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ecapri...@apache.org
Subject [4/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project
Date Thu, 13 Apr 2017 16:15:54 GMT
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> {
-
-}
-



Mime
View raw message