You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gossip.apache.org by ec...@apache.org on 2017/04/13 16:15:51 UTC

[1/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project

Repository: incubator-gossip
Updated Branches:
  refs/heads/master 6a4d50cae -> 298b1ae3a


http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/test/java/org/apache/gossip/DataTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/DataTest.java b/src/test/java/org/apache/gossip/DataTest.java
deleted file mode 100644
index f0c2186..0000000
--- a/src/test/java/org/apache/gossip/DataTest.java
+++ /dev/null
@@ -1,238 +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.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.gossip.crdt.GrowOnlyCounter;
-import org.apache.gossip.crdt.GrowOnlySet;
-import org.apache.gossip.crdt.OrSet;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-import org.apache.gossip.model.PerNodeDataMessage;
-import org.apache.gossip.model.SharedDataMessage;
-import org.junit.Test;
-
-import io.teknek.tunit.TUnit;
-
-public class DataTest extends AbstractIntegrationBase {
-  
-  private String orSetKey = "cror";
-  private String gCounterKey = "crdtgc";
-  
-  @Test
-  public void dataTest() throws InterruptedException, UnknownHostException, URISyntaxException{
-    GossipSettings settings = new GossipSettings();
-    settings.setPersistRingState(false);
-    settings.setPersistDataState(false);
-    String cluster = UUID.randomUUID().toString();
-    int seedNodes = 1;
-    List<Member> startupMembers = new ArrayList<>();
-    for (int i = 1; i < seedNodes+1; ++i) {
-      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
-      startupMembers.add(new RemoteMember(cluster, uri, i + ""));
-    }
-    final List<GossipManager> clients = new ArrayList<>();
-    final int clusterMembers = 2;
-    for (int i = 1; i < clusterMembers + 1; ++i) {
-      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
-      GossipManager gossipService = GossipManagerBuilder.newBuilder().cluster(cluster).uri(uri)
-              .id(i + "").gossipMembers(startupMembers).gossipSettings(settings).build();
-      clients.add(gossipService);
-      gossipService.init();
-      register(gossipService);
-    }
-    TUnit.assertThat(() -> {
-      int total = 0;
-      for (int i = 0; i < clusterMembers; ++i) {
-        total += clients.get(i).getLiveMembers().size();
-      }
-      return total;
-    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo(2);
-    clients.get(0).gossipPerNodeData(msg());
-    clients.get(0).gossipSharedData(sharedMsg());
-
-    TUnit.assertThat(()-> {
-      PerNodeDataMessage x = clients.get(1).findPerNodeGossipData(1 + "", "a");
-      if (x == null)
-        return "";
-      else
-        return x.getPayload();
-    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo("b");
-   
-    TUnit.assertThat(() ->  {
-      SharedDataMessage x = clients.get(1).findSharedGossipData("a");
-      if (x == null)
-        return "";
-      else
-        return x.getPayload();
-    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo("c");
-    
-    
-    givenDifferentDatumsInSet(clients);
-    assertThatListIsMerged(clients);
-    
-    givenOrs(clients);
-    assertThatOrSetIsMerged(clients);
-    dropIt(clients);
-    assertThatOrSetDelIsMerged(clients);
-
-    
-    // test g counter
-    givenDifferentIncrement(clients);
-    assertThatCountIsUpdated(clients, 3);
-    givenIncreaseOther(clients);
-    assertThatCountIsUpdated(clients, 7);
-
-    for (int i = 0; i < clusterMembers; ++i) {
-      clients.get(i).shutdown();
-    }
-  }
-  
-  private void givenDifferentIncrement(final List<GossipManager> clients) {
-    {
-      SharedDataMessage d = new SharedDataMessage();
-      d.setKey(gCounterKey);
-      d.setPayload(new GrowOnlyCounter(new GrowOnlyCounter.Builder(clients.get(0)).increment(1L)));
-      d.setExpireAt(Long.MAX_VALUE);
-      d.setTimestamp(System.currentTimeMillis());
-      clients.get(0).merge(d);
-    }
-    {
-      SharedDataMessage d = new SharedDataMessage();
-      d.setKey(gCounterKey);
-      d.setPayload(new GrowOnlyCounter(new GrowOnlyCounter.Builder(clients.get(1)).increment(2L)));
-      d.setExpireAt(Long.MAX_VALUE);
-      d.setTimestamp(System.currentTimeMillis());
-      clients.get(1).merge(d);
-    }
-  }
-
-  private void givenIncreaseOther(final List<GossipManager> clients) {
-    GrowOnlyCounter gc = (GrowOnlyCounter) clients.get(1).findCrdt(gCounterKey);
-    GrowOnlyCounter gc2 = new GrowOnlyCounter(gc,
-            new GrowOnlyCounter.Builder(clients.get(1)).increment(4L));
-
-    SharedDataMessage d = new SharedDataMessage();
-    d.setKey(gCounterKey);
-    d.setPayload(gc2);
-    d.setExpireAt(Long.MAX_VALUE);
-    d.setTimestamp(System.currentTimeMillis());
-    clients.get(1).merge(d);
-  }
-
-  private void givenOrs(List<GossipManager> clients) {
-    {
-      SharedDataMessage d = new SharedDataMessage();
-      d.setKey(orSetKey);
-      d.setPayload(new OrSet<String>("1", "2"));
-      d.setExpireAt(Long.MAX_VALUE);
-      d.setTimestamp(System.currentTimeMillis());
-      clients.get(0).merge(d);
-    }
-    {
-      SharedDataMessage d = new SharedDataMessage();
-      d.setKey(orSetKey);
-      d.setPayload(new OrSet<String>("3", "4"));
-      d.setExpireAt(Long.MAX_VALUE);
-      d.setTimestamp(System.currentTimeMillis());
-      clients.get(1).merge(d);
-    }
-  }
-  
-  private void dropIt(List<GossipManager> clients) {
-    @SuppressWarnings("unchecked")
-    OrSet<String> o = (OrSet<String>) clients.get(0).findCrdt(orSetKey);
-    OrSet<String> o2 = new OrSet<String>(o, new OrSet.Builder<String>().remove("3"));
-    SharedDataMessage d = new SharedDataMessage();
-    d.setKey(orSetKey);
-    d.setPayload(o2);
-    d.setExpireAt(Long.MAX_VALUE);
-    d.setTimestamp(System.currentTimeMillis());
-    clients.get(0).merge(d);
-  }
-  
-  private void assertThatOrSetIsMerged(final List<GossipManager> clients){
-    TUnit.assertThat(() ->  {
-      return clients.get(0).findCrdt(orSetKey).value();
-    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new OrSet<String>("1", "2", "3", "4").value());
-    TUnit.assertThat(() ->  {
-      return clients.get(1).findCrdt(orSetKey).value();
-    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new OrSet<String>("1", "2", "3", "4").value());
-  }
-  
-  private void assertThatOrSetDelIsMerged(final List<GossipManager> clients){
-    TUnit.assertThat(() ->  {
-      return clients.get(0).findCrdt(orSetKey);
-    }).afterWaitingAtMost(10, TimeUnit.SECONDS).equals(new OrSet<String>("1", "2", "4"));
-  }
-
-  private void givenDifferentDatumsInSet(final List<GossipManager> clients){
-    clients.get(0).merge(CrdtMessage("1"));
-    clients.get(1).merge(CrdtMessage("2"));
-  }
-  
-
-  private void assertThatCountIsUpdated(final List<GossipManager> clients, long finalCount) {
-    TUnit.assertThat(() -> {
-      return clients.get(0).findCrdt(gCounterKey);
-    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new GrowOnlyCounter(
-            new GrowOnlyCounter.Builder(clients.get(0)).increment(finalCount)));
-  }
-
-  private void assertThatListIsMerged(final List<GossipManager> clients){
-    TUnit.assertThat(() ->  {
-      return clients.get(0).findCrdt("cr");
-    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new GrowOnlySet<String>(Arrays.asList("1","2")));
-  }
-  
-  private SharedDataMessage CrdtMessage(String item){
-    SharedDataMessage d = new SharedDataMessage();
-    d.setKey("cr");
-    d.setPayload(new GrowOnlySet<String>( Arrays.asList(item)));
-    d.setExpireAt(Long.MAX_VALUE);
-    d.setTimestamp(System.currentTimeMillis());
-    return d;
-  }
-  
-  private PerNodeDataMessage msg(){
-    PerNodeDataMessage g = new PerNodeDataMessage();
-    g.setExpireAt(Long.MAX_VALUE);
-    g.setKey("a");
-    g.setPayload("b");
-    g.setTimestamp(System.currentTimeMillis());
-    return g;
-  }
-  
-  private SharedDataMessage sharedMsg(){
-    SharedDataMessage g = new SharedDataMessage();
-    g.setExpireAt(Long.MAX_VALUE);
-    g.setKey("a");
-    g.setPayload("c");
-    g.setTimestamp(System.currentTimeMillis());
-    return g;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/test/java/org/apache/gossip/IdAndPropertyTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/IdAndPropertyTest.java b/src/test/java/org/apache/gossip/IdAndPropertyTest.java
deleted file mode 100644
index 7f550de..0000000
--- a/src/test/java/org/apache/gossip/IdAndPropertyTest.java
+++ /dev/null
@@ -1,91 +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.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit; 
-
-import org.apache.gossip.manager.DatacenterRackAwareActiveGossiper;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-import org.junit.jupiter.api.Test;
-import org.junit.platform.runner.JUnitPlatform;
-import org.junit.runner.RunWith;
-
-import io.teknek.tunit.TUnit;
-
-@RunWith(JUnitPlatform.class)
-public class IdAndPropertyTest extends AbstractIntegrationBase {
-
-  @Test
-  public void testDatacenterRackGossiper() throws URISyntaxException, UnknownHostException, InterruptedException {
-    GossipSettings settings = new GossipSettings();
-    settings.setActiveGossipClass(DatacenterRackAwareActiveGossiper.class.getName());
-    List<Member> startupMembers = new ArrayList<>();
-    Map<String, String> x = new HashMap<>();
-    x.put("a", "b");
-    x.put("datacenter", "dc1");
-    x.put("rack", "rack1");
-    GossipManager gossipService1 = GossipManagerBuilder.newBuilder()
-            .cluster("a")
-            .uri(new URI("udp://" + "127.0.0.1" + ":" + (29000 + 0)))
-            .id("0")
-            .properties(x)
-            .gossipMembers(startupMembers)
-            .gossipSettings(settings).build();
-    gossipService1.init();
-    register(gossipService1);
-    
-    Map<String, String> y = new HashMap<>();
-    y.put("a", "c");
-    y.put("datacenter", "dc2");
-    y.put("rack", "rack2");
-    GossipManager gossipService2 = GossipManagerBuilder.newBuilder().cluster("a")
-            .uri( new URI("udp://" + "127.0.0.1" + ":" + (29000 + 10)))
-            .id("1")
-            .properties(y)
-            .gossipMembers(Arrays.asList(new RemoteMember("a",
-                    new URI("udp://" + "127.0.0.1" + ":" + (29000 + 0)), "0")))
-            .gossipSettings(settings).build();
-    gossipService2.init();
-    register(gossipService2);
-    
-    TUnit.assertThat(() -> { 
-      String value = ""; 
-      try {
-        value = gossipService1.getLiveMembers().get(0).getProperties().get("a");
-      } catch (RuntimeException e){ }
-      return value;
-    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo("c");
-    
-    TUnit.assertThat(() -> { 
-      String value = ""; 
-      try {
-        value = gossipService2.getLiveMembers().get(0).getProperties().get("a");
-      } catch (RuntimeException e){ }
-      return value;
-    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo("b");        
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/test/java/org/apache/gossip/MemberTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/MemberTest.java b/src/test/java/org/apache/gossip/MemberTest.java
deleted file mode 100644
index 5f0d18a..0000000
--- a/src/test/java/org/apache/gossip/MemberTest.java
+++ /dev/null
@@ -1,40 +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.net.URISyntaxException;
-import java.util.HashMap;
-
-import org.junit.Assert;
-import org.junit.jupiter.api.Test;
-import org.junit.platform.runner.JUnitPlatform;
-import org.junit.runner.RunWith;
-
-@RunWith(JUnitPlatform.class)
-public class MemberTest {
-
-  @Test
-  public void testHashCodeFromGossip40() throws URISyntaxException {
-    Assert.assertNotEquals(
-            new LocalMember("mycluster", new URI("udp://4.4.4.4:1000"), "myid", 1, new HashMap<String,String>(), 10, 5, "exponential")
-                    .hashCode(),
-            new LocalMember("mycluster", new URI("udp://4.4.4.5:1005"), "yourid", 11, new HashMap<String,String>(), 11, 6, "exponential")
-                    .hashCode());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java b/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java
deleted file mode 100644
index 54005c3..0000000
--- a/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java
+++ /dev/null
@@ -1,146 +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 io.teknek.tunit.TUnit;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-import org.apache.log4j.Logger;
-
-import org.junit.platform.runner.JUnitPlatform;
-import org.junit.jupiter.api.Test;
-
-import org.junit.runner.RunWith;
-
-@RunWith(JUnitPlatform.class)
-public class ShutdownDeadtimeTest {
-
-  private static final Logger log = Logger.getLogger(ShutdownDeadtimeTest.class);
-  
-  @Test
-  public void DeadNodesDoNotComeAliveAgain()
-          throws InterruptedException, UnknownHostException, URISyntaxException {
-    GossipSettings settings = new GossipSettings(100, 10000, 1000, 1, 10.0, "normal");
-    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" + ":" + (30300 + i));
-      startupMembers.add(new RemoteMember(cluster, uri, i + ""));
-    }
-    final List<GossipManager> clients = Collections.synchronizedList(new ArrayList<GossipManager>());
-    final int clusterMembers = 5;
-    for (int i = 1; i < clusterMembers + 1; ++i) {
-      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30300 + i));
-      GossipManager gossipService = GossipManagerBuilder.newBuilder()
-              .cluster(cluster)
-              .uri(uri)
-              .id(i + "")
-              .gossipMembers(startupMembers)
-              .gossipSettings(settings)
-              .build();
-      clients.add(gossipService);
-      gossipService.init();
-      
-    }
-    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);
-
-    // shutdown one client and verify that one client is lost.
-    Random r = new Random();
-    int randomClientId = r.nextInt(clusterMembers);
-    log.info("shutting down " + randomClientId);
-    final int shutdownPort = clients.get(randomClientId).getMyself().getUri()
-            .getPort();
-    final String shutdownId = clients.get(randomClientId).getMyself().getId();
-    clients.get(randomClientId).shutdown();
-    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(16);
-    clients.remove(randomClientId);
-
-    TUnit.assertThat(new Callable<Integer>() {
-      public Integer call() throws Exception {
-        int total = 0;
-        for (int i = 0; i < clusterMembers - 1; ++i) {
-          total += clients.get(i).getDeadMembers().size();
-        }
-        return total;
-      }
-    }).afterWaitingAtMost(50, TimeUnit.SECONDS).isEqualTo(4);
-
-    URI uri = new URI("udp://" + "127.0.0.1" + ":" + shutdownPort);
-    // start client again
-    GossipManager gossipService = GossipManagerBuilder.newBuilder()
-            .gossipSettings(settings)
-            .cluster(cluster)
-            .uri(uri)
-            .id(shutdownId+"")
-            .gossipMembers(startupMembers)
-            .build();
-    clients.add(gossipService);
-    gossipService.init();
-
-    // verify that the client is alive again for every node
-    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(60, TimeUnit.SECONDS).isEqualTo(20);
-
-    for (int i = 0; i < clusterMembers; ++i) {
-      final 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/src/test/java/org/apache/gossip/SignedMessageTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/SignedMessageTest.java b/src/test/java/org/apache/gossip/SignedMessageTest.java
deleted file mode 100644
index 5c3bb76..0000000
--- a/src/test/java/org/apache/gossip/SignedMessageTest.java
+++ /dev/null
@@ -1,135 +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.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-import org.apache.gossip.manager.PassiveGossipConstants;
-import org.apache.gossip.secure.KeyTool;
-import org.junit.Assert;
-import org.junit.Test;
-
-import io.teknek.tunit.TUnit;
-
-public class SignedMessageTest extends AbstractIntegrationBase {
-
-  @Test(expected = IllegalArgumentException.class)
-  public void ifSignMustHaveKeys()
-          throws URISyntaxException, UnknownHostException, InterruptedException {
-    String cluster = UUID.randomUUID().toString();
-    GossipSettings settings = gossiperThatSigns();
-    List<Member> startupMembers = new ArrayList<>();
-    URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30000 + 1));
-    GossipManager gossipService = GossipManagerBuilder.newBuilder()
-            .cluster(cluster)
-            .uri(uri)
-            .id(1 + "")
-            .gossipMembers(startupMembers)
-            .gossipSettings(settings)
-            .build();
-    gossipService.init();
-  }
-
-  private GossipSettings gossiperThatSigns(){
-    GossipSettings settings = new GossipSettings();
-    settings.setPersistRingState(false);
-    settings.setPersistDataState(false);
-    settings.setSignMessages(true);
-    return settings;
-  }
-  
-  private GossipSettings gossiperThatSigns(String keysDir){
-    GossipSettings settings = gossiperThatSigns();
-    settings.setPathToKeyStore(Objects.requireNonNull(keysDir));
-    return settings;
-  }
-  
-  @Test
-  public void dataTest() throws InterruptedException, URISyntaxException, NoSuchAlgorithmException, NoSuchProviderException, IOException {
-    final String keys = System.getProperty("java.io.tmpdir") + "/keys";
-    GossipSettings settings = gossiperThatSigns(keys);
-    setup(keys);
-    String cluster = UUID.randomUUID().toString();
-    List<Member> startupMembers = new ArrayList<>();
-    for (int i = 1; i < 2; ++i) {
-      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30000 + i));
-      startupMembers.add(new RemoteMember(cluster, uri, i + ""));
-    }
-    final List<GossipManager> clients = new ArrayList<>();
-    for (int i = 1; i < 3; ++i) {
-      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30000 + i));
-      GossipManager gossipService = GossipManagerBuilder.newBuilder()
-              .cluster(cluster)
-              .uri(uri)
-              .id(i + "")
-              .gossipMembers(startupMembers)
-              .gossipSettings(settings)
-              .build();
-      gossipService.init();
-      clients.add(gossipService);
-    }
-    assertTwoAlive(clients);
-    assertOnlySignedMessages(clients);
-    cleanup(keys, clients);
-  }
-  
-  private void assertTwoAlive(List<GossipManager> clients){
-    TUnit.assertThat(() -> {
-      int total = 0;
-      for (int i = 0; i < clients.size(); ++i) {
-        total += clients.get(i).getLiveMembers().size();
-      }
-      return total;
-    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo(2);
-  }
-  
-  private void assertOnlySignedMessages(List<GossipManager> clients){
-    Assert.assertEquals(0, clients.get(0).getRegistry()
-            .meter(PassiveGossipConstants.UNSIGNED_MESSAGE).getCount());
-    Assert.assertTrue(clients.get(0).getRegistry()
-            .meter(PassiveGossipConstants.SIGNED_MESSAGE).getCount() > 0);
-  }
-  
-  private void cleanup(String keys, List<GossipManager> clients){
-    new File(keys, "1").delete();
-    new File(keys, "2").delete();
-    new File(keys).delete();
-    for (int i = 0; i < clients.size(); ++i) {
-      clients.get(i).shutdown();
-    }
-  }
-  
-  private void setup(String keys) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
-    new File(keys).mkdir();
-    KeyTool.generatePubandPrivateKeyFiles(keys, "1");
-    KeyTool.generatePubandPrivateKeyFiles(keys, "2");
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/test/java/org/apache/gossip/StartupSettingsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/StartupSettingsTest.java b/src/test/java/org/apache/gossip/StartupSettingsTest.java
deleted file mode 100644
index d6c4a1e..0000000
--- a/src/test/java/org/apache/gossip/StartupSettingsTest.java
+++ /dev/null
@@ -1,86 +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 org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-import org.apache.log4j.Logger;
-
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.UUID;
-import org.junit.platform.runner.JUnitPlatform;
-import org.junit.runner.RunWith;
-
-/**
- * Tests support of using {@code StartupSettings} and thereby reading
- * setup config from file.
- */
-@RunWith(JUnitPlatform.class)
-public class StartupSettingsTest {
-  private static final Logger log = Logger.getLogger(StartupSettingsTest.class);
-  private static final String CLUSTER = UUID.randomUUID().toString();
-
-  @Test
-  public void testUsingSettingsFile() throws IOException, InterruptedException, URISyntaxException {
-    File settingsFile = File.createTempFile("gossipTest",".json");
-    settingsFile.deleteOnExit();
-    writeSettingsFile(settingsFile);
-    URI uri = new URI("udp://" + "127.0.0.1" + ":" + 50000);
-    GossipManager firstService = GossipManagerBuilder.newBuilder()
-            .cluster(CLUSTER)
-            .uri(uri)
-            .id("1")
-            .gossipSettings(new GossipSettings()).build();
-    firstService.init();
-    GossipManager manager = GossipManagerBuilder.newBuilder()
-            .startupSettings(StartupSettings.fromJSONFile(settingsFile)).build();
-    manager.init();
-    firstService.shutdown();
-    manager.shutdown();
-  }
-
-  private void writeSettingsFile( File target ) throws IOException {
-    String settings =
-            "[{\n" + // It is odd that this is meant to be in an array, but oh well.
-            "  \"cluster\":\"" + CLUSTER + "\",\n" +
-            "  \"id\":\"" + "2" + "\",\n" +
-            "  \"uri\":\"udp://127.0.0.1:50001\",\n" +
-            "  \"gossip_interval\":1000,\n" +
-            "  \"window_size\":1000,\n" +
-            "  \"minimum_samples\":5,\n" +
-            "  \"cleanup_interval\":10000,\n" +
-            "  \"convict_threshold\":2.6,\n" +
-            "  \"distribution\":\"exponential\",\n" +
-            "  \"properties\":{},\n" +
-            "  \"members\":[\n" +
-            "    {\"cluster\": \"" + CLUSTER + "\",\"uri\":\"udp://127.0.0.1:5000\"}\n" +
-            "  ]\n" +
-            "}]";
-
-    log.info( "Using settings file with contents of:\n---\n" + settings + "\n---" );
-    FileOutputStream output = new FileOutputStream(target);
-    output.write(settings.getBytes());
-    output.close();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java b/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java
deleted file mode 100644
index 8ae783e..0000000
--- a/src/test/java/org/apache/gossip/TenNodeThreeSeedTest.java
+++ /dev/null
@@ -1,92 +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 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/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java b/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java
deleted file mode 100644
index 3434c17..0000000
--- a/src/test/java/org/apache/gossip/accrual/FailureDetectorTest.java
+++ /dev/null
@@ -1,113 +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.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/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java b/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java
deleted file mode 100644
index 3a134af..0000000
--- a/src/test/java/org/apache/gossip/crdt/GrowOnlyCounterTest.java
+++ /dev/null
@@ -1,54 +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 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/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java b/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java
deleted file mode 100644
index d4f12b6..0000000
--- a/src/test/java/org/apache/gossip/crdt/GrowOnlySetTest.java
+++ /dev/null
@@ -1,38 +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.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/src/test/java/org/apache/gossip/crdt/OrSetTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/crdt/OrSetTest.java b/src/test/java/org/apache/gossip/crdt/OrSetTest.java
deleted file mode 100644
index b19f221..0000000
--- a/src/test/java/org/apache/gossip/crdt/OrSetTest.java
+++ /dev/null
@@ -1,115 +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.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/src/test/java/org/apache/gossip/manager/DataReaperTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/manager/DataReaperTest.java b/src/test/java/org/apache/gossip/manager/DataReaperTest.java
deleted file mode 100644
index e328c24..0000000
--- a/src/test/java/org/apache/gossip/manager/DataReaperTest.java
+++ /dev/null
@@ -1,104 +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.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/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java b/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java
deleted file mode 100644
index 8842643..0000000
--- a/src/test/java/org/apache/gossip/manager/GossipManagerBuilderTest.java
+++ /dev/null
@@ -1,121 +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.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/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java b/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java
deleted file mode 100644
index d448b98..0000000
--- a/src/test/java/org/apache/gossip/manager/RingPersistenceTest.java
+++ /dev/null
@@ -1,64 +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.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/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java b/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java
deleted file mode 100644
index 7b17e41..0000000
--- a/src/test/java/org/apache/gossip/manager/UserDataPersistenceTest.java
+++ /dev/null
@@ -1,114 +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.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/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java b/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java
deleted file mode 100644
index 571d7ba..0000000
--- a/src/test/java/org/apache/gossip/manager/handlers/MessageInvokerTest.java
+++ /dev/null
@@ -1,178 +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.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/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties
deleted file mode 100644
index e2a60e1..0000000
--- a/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#  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


[3/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project

Posted by ec...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java b/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java
deleted file mode 100644
index dd1505a..0000000
--- a/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java
+++ /dev/null
@@ -1,119 +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 org.apache.gossip.manager.GossipManager;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class GrowOnlyCounter implements CrdtCounter<Long, GrowOnlyCounter> {
-  
-  private final Map<String, Long> counters = new HashMap<>();
-  
-  GrowOnlyCounter(Map<String, Long> counters) {
-    this.counters.putAll(counters);
-  }
-  
-  public GrowOnlyCounter(GrowOnlyCounter growOnlyCounter, Builder builder) {
-    counters.putAll(growOnlyCounter.counters);
-    if (counters.containsKey(builder.myId)) {
-      Long newValue = counters.get(builder.myId) + builder.counter;
-      counters.replace(builder.myId, newValue);
-    } else {
-      counters.put(builder.myId, builder.counter);
-    }
-  }
-  
-  public GrowOnlyCounter(Builder builder) {
-    counters.put(builder.myId, builder.counter);
-  }
-  
-  public GrowOnlyCounter(GossipManager manager) {
-    counters.put(manager.getMyself().getId(), 0L);
-  }
-  
-  public GrowOnlyCounter(GrowOnlyCounter growOnlyCounter, GrowOnlyCounter other) {
-    counters.putAll(growOnlyCounter.counters);
-    for (Map.Entry<String, Long> entry : other.counters.entrySet()) {
-      String otherKey = entry.getKey();
-      Long otherValue = entry.getValue();
-      
-      if (counters.containsKey(otherKey)) {
-        Long newValue = Math.max(counters.get(otherKey), otherValue);
-        counters.replace(otherKey, newValue);
-      } else {
-        counters.put(otherKey, otherValue);
-      }
-    }
-  }
-  
-  @Override
-  public GrowOnlyCounter merge(GrowOnlyCounter other) {
-    return new GrowOnlyCounter(this, other);
-  }
-  
-  @Override
-  public Long value() {
-    Long globalCount = 0L;
-    for (Long increment : counters.values()) {
-      globalCount += increment;
-    }
-    return globalCount;
-  }
-  
-  @Override
-  public GrowOnlyCounter optimize() {
-    return new GrowOnlyCounter(counters);
-  }
-  
-  @Override
-  public boolean equals(Object obj) {
-    if (getClass() != obj.getClass())
-      return false;
-    GrowOnlyCounter other = (GrowOnlyCounter) obj;
-    return value().longValue() == other.value().longValue();
-  }
-  
-  @Override
-  public String toString() {
-    return "GrowOnlyCounter [counters= " + counters + ", Value=" + value() + "]";
-  }
-  
-  Map<String, Long> getCounters() {
-    return counters;
-  }
-  
-  public static class Builder {
-    
-    private final String myId;
-    
-    private Long counter;
-    
-    public Builder(GossipManager gossipManager) {
-      myId = gossipManager.getMyself().getId();
-      counter = 0L;
-    }
-    
-    public GrowOnlyCounter.Builder increment(Long count) {
-      counter += count;
-      return this;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java b/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java
deleted file mode 100644
index 9e2dd49..0000000
--- a/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java
+++ /dev/null
@@ -1,157 +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.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-public class GrowOnlySet<ElementType> implements CrdtSet<ElementType, Set<ElementType>, GrowOnlySet<ElementType>>{
-
-  private final Set<ElementType> hidden = new LinkedHashSet<>();
-  
-  @SuppressWarnings("unused")
-  /*
-   * Used by SerDe
-   */
-  private GrowOnlySet(){
-    
-  }
-  
-  public GrowOnlySet(Set<ElementType> c){
-    hidden.addAll(c);
-  }
-  
-  public GrowOnlySet(Collection<ElementType> c){
-    hidden.addAll(c);
-  }
-  
-  public GrowOnlySet(GrowOnlySet<ElementType> first, GrowOnlySet<ElementType> second){
-    hidden.addAll(first.value());
-    hidden.addAll(second.value());
-  }
-  
-  @Override
-  public GrowOnlySet<ElementType> merge(GrowOnlySet<ElementType> other) {
-    return new GrowOnlySet<>(this, other);
-  }
-
-  @Override
-  public Set<ElementType> value() {
-    Set<ElementType> copy = new LinkedHashSet<>();
-    copy.addAll(hidden);
-    return Collections.unmodifiableSet(copy);
-  }
-  
-  @Override
-  public GrowOnlySet<ElementType> optimize() {
-    return new GrowOnlySet<>(hidden);
-  }
-
-  public int size() {
-    return hidden.size();
-  }
-
-  public boolean isEmpty() {
-    return hidden.isEmpty();
-  }
-
-  public boolean contains(Object o) {
-    return hidden.contains(o);
-  }
-
-  public Iterator<ElementType> iterator() {
-    Set<ElementType> copy = new HashSet<>();
-    copy.addAll(hidden);
-    return copy.iterator();
-  }
-
-  public Object[] toArray() {
-    return hidden.toArray();
-  }
-
-  public <T> T[] toArray(T[] a) {
-    return hidden.toArray(a);
-  }
-
-  public boolean add(ElementType e) {
-    throw new UnsupportedOperationException();
-  }
-
-  public boolean remove(Object o) {
-    throw new UnsupportedOperationException();
-  }
-
-  public boolean containsAll(Collection<?> c) {
-    return hidden.containsAll(c);
-  }
-
-  public boolean addAll(Collection<? extends ElementType> c) {
-    throw new UnsupportedOperationException();
-  }
-
-  public boolean retainAll(Collection<?> c) {
-    throw new UnsupportedOperationException();
-  }
-
-  public boolean removeAll(Collection<?> c) {
-    throw new UnsupportedOperationException();
-  }
-
-  public void clear() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String toString() {
-    return "GrowOnlySet [hidden=" + hidden + "]";
-  }
-
-  @Override
-  public int hashCode() {
-    final int prime = 31;
-    int result = 1;
-    result = prime * result + ((hidden == null) ? 0 : hidden.hashCode());
-    return result;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj)
-      return true;
-    if (obj == null)
-      return false;
-    if (getClass() != obj.getClass())
-      return false;
-    @SuppressWarnings("rawtypes")
-    GrowOnlySet other = (GrowOnlySet) obj;
-    if (hidden == null) {
-      if (other.hidden != null)
-        return false;
-    } else if (!hidden.equals(other.hidden))
-      return false;
-    return true;
-  }
-
-  Set<ElementType> getElements(){
-    return hidden;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/crdt/OrSet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/crdt/OrSet.java b/src/main/java/org/apache/gossip/crdt/OrSet.java
deleted file mode 100644
index f84dbc7..0000000
--- a/src/main/java/org/apache/gossip/crdt/OrSet.java
+++ /dev/null
@@ -1,304 +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.*;
-import java.util.Map.Entry;
-import java.util.function.BiConsumer;
-
-import org.apache.gossip.crdt.OrSet.Builder.Operation;
-
-/*
- * A immutable set 
- */
-public class OrSet<E>  implements Crdt<Set<E>, OrSet<E>> {
-  
-  private final Map<E, Set<UUID>> elements = new HashMap<>();
-  private final Map<E, Set<UUID>> tombstones = new HashMap<>();
-  private final transient Set<E> val;
-  
-  public OrSet(){
-    val = computeValue();
-  }
-  
-  OrSet(Map<E, Set<UUID>> elements, Map<E, Set<UUID>> tombstones){
-    this.elements.putAll(elements);
-    this.tombstones.putAll(tombstones);
-    val = computeValue();
-  }
-  
-  @SafeVarargs
-  public OrSet(E ... elements){
-    for (E e: elements){
-      internalAdd(e);
-    }
-    val = computeValue();
-  }
-  
-  public OrSet(Builder<E>builder){
-    for (Builder<E>.OrSetElement<E> e: builder.elements){
-      if (e.operation == Operation.ADD){
-        internalAdd(e.element);
-      } else {
-        internalRemove(e.element);
-      }
-    }
-    val = computeValue();
-  }
-  
-  /**
-   * This constructor is the way to remove elements from an existing set
-   * @param set
-   * @param builder 
-   */
-  public OrSet(OrSet<E> set, Builder<E> builder){
-    elements.putAll(set.elements);
-    tombstones.putAll(set.tombstones);
-    for (Builder<E>.OrSetElement<E> e: builder.elements){
-      if (e.operation == Operation.ADD){
-        internalAdd(e.element);
-      } else {
-        internalRemove(e.element);
-      }
-    }
-    val = computeValue();
-  }
-
-  static Set<UUID> mergeSets(Set<UUID> a, Set<UUID> b) {
-    if ((a == null || a.isEmpty()) && (b == null || b.isEmpty())) {
-      return null;
-    }
-    Set<UUID> res = new HashSet<>(a);
-    res.addAll(b);
-    return res;
-  }
-
-  private void internalSetMerge(Map<E, Set<UUID>> map, E key, Set<UUID> value) {
-    if (value == null) {
-      return;
-    }
-    map.merge(key, value, OrSet::mergeSets);
-  }
-
-  public OrSet(OrSet<E> left, OrSet<E> right){
-    BiConsumer<Map<E, Set<UUID>>, Map<E, Set<UUID>>> internalMerge = (items, other) -> {
-      for (Entry<E, Set<UUID>> l : other.entrySet()){
-        internalSetMerge(items, l.getKey(), l.getValue());
-      }
-    };
-
-    internalMerge.accept(elements, left.elements);
-    internalMerge.accept(elements, right.elements);
-    internalMerge.accept(tombstones, left.tombstones);
-    internalMerge.accept(tombstones, right.tombstones);
-
-    val = computeValue();
-  }
-  
-  public OrSet.Builder<E> builder(){
-    return new OrSet.Builder<>();
-  }
-  
-  @Override
-  public OrSet<E> merge(OrSet<E> other) {
-    return new OrSet<E>(this, other);
-  }
-  
-  private void internalAdd(E element) {
-    Set<UUID> toMerge = new HashSet<>();
-    toMerge.add(UUID.randomUUID());
-    internalSetMerge(elements, element, toMerge);
-  }
-  
-  private void internalRemove(E element){
-    internalSetMerge(tombstones, element, elements.get(element));
-  }
-
-  /*
-   * Computes the live values by analyzing the elements and tombstones
-   */
-  private Set<E> computeValue(){
-    Set<E> values = new HashSet<>();
-    for (Entry<E, Set<UUID>> entry: elements.entrySet()){
-      Set<UUID> deleteIds = tombstones.get(entry.getKey());
-      // if not all tokens for current element are in tombstones
-      if (deleteIds == null || !deleteIds.containsAll(entry.getValue())) {
-        values.add(entry.getKey());
-      }
-    }
-    return values;
-  }
-  
-  @Override
-  public Set<E> value() {
-    return val;
-  }
-
-  @Override
-  public OrSet<E> optimize() {
-    return this;
-  }
-  
-  public static class Builder<E> {
-    public static enum Operation {
-      ADD, REMOVE
-    };
-
-    private class OrSetElement<EL> {
-      EL element;
-      Operation operation;
-
-      private OrSetElement(EL element, Operation operation) {
-        this.element = element;
-        this.operation = operation;
-      }
-    }
-
-    private List<OrSetElement<E>> elements = new ArrayList<>();
-
-    public Builder<E> add(E element) {
-      elements.add(new OrSetElement<E>(element, Operation.ADD));
-      return this;
-    }
-
-    public Builder<E> remove(E element) {
-      elements.add(new OrSetElement<E>(element, Operation.REMOVE));
-      return this;
-    }
-
-    public Builder<E> mutate(E element, Operation operation) {
-      elements.add(new OrSetElement<E>(element, operation));
-      return this;
-    }
-  }
-
-  
-  public int size() {
-    return value().size();
-  }
-
-  
-  public boolean isEmpty() {
-    return value().size() == 0;
-  }
-
-  
-  public boolean contains(Object o) {
-    return value().contains(o);
-  }
-
-  
-  public Iterator<E> iterator() {
-    Iterator<E> managed = value().iterator();
-    return new Iterator<E>() {
-
-      @Override
-      public void remove() {
-        throw new IllegalArgumentException();
-      }
-
-      @Override
-      public boolean hasNext() {
-        return managed.hasNext();
-      }
-
-      @Override
-      public E next() {
-        return managed.next();
-      }
-      
-    };
-  }
-
-  public Object[] toArray() {
-    return value().toArray();
-  }
-
-  public <T> T[] toArray(T[] a) {
-    return value().toArray(a);
-  }
-
-  public boolean add(E e) {
-    throw new IllegalArgumentException("Can not add");
-  }
-
-
-  public boolean remove(Object o) {
-    throw new IllegalArgumentException();
-  }
-
-  public boolean containsAll(Collection<?> c) {
-    return this.value().containsAll(c);
-  }
-
-  public boolean addAll(Collection<? extends E> c) {
-    throw new IllegalArgumentException();
-  }
-
-  public boolean retainAll(Collection<?> c) {
-    throw new IllegalArgumentException();
-  }
-
-  public boolean removeAll(Collection<?> c) {
-    throw new IllegalArgumentException();
-  }
-
-  public void clear() {
-    throw new IllegalArgumentException();
-  }
-
-  @Override
-  public String toString() {
-    return "OrSet [elements=" + elements + ", tombstones=" + tombstones + "]" ;
-  }
-
-  @Override
-  public int hashCode() {
-    final int prime = 31;
-    int result = 1;
-    result = prime * result + ((value() == null) ? 0 : value().hashCode());
-    return result;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj)
-      return true;
-    if (obj == null)
-      return false;
-    if (getClass() != obj.getClass())
-      return false;
-    @SuppressWarnings("rawtypes")
-    OrSet other = (OrSet) obj;
-    if (elements == null) {
-      if (other.elements != null)
-        return false;
-    } else if (!value().equals(other.value()))
-      return false;
-    return true;
-  }
-
-  Map<E, Set<UUID>> getElements() {
-    return elements;
-  }
-
-  Map<E, Set<UUID>> getTombstones() {
-    return tombstones;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/event/GossipListener.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/event/GossipListener.java b/src/main/java/org/apache/gossip/event/GossipListener.java
deleted file mode 100644
index 9b33dab..0000000
--- a/src/main/java/org/apache/gossip/event/GossipListener.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.event;
-
-import org.apache.gossip.Member;
-
-public interface GossipListener {
-  void gossipEvent(Member member, GossipState state);
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/event/GossipState.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/event/GossipState.java b/src/main/java/org/apache/gossip/event/GossipState.java
deleted file mode 100644
index 3b76c9e..0000000
--- a/src/main/java/org/apache/gossip/event/GossipState.java
+++ /dev/null
@@ -1,28 +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.event;
-
-public enum GossipState {
-  UP("up"), DOWN("down");
-  @SuppressWarnings("unused")
-  private final String state;
-
-  private GossipState(String state) {
-    this.state = state;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java b/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
deleted file mode 100644
index 497894c..0000000
--- a/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
+++ /dev/null
@@ -1,62 +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.examples;
-
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.gossip.GossipSettings;
-import org.apache.gossip.RemoteMember;
-import org.apache.gossip.manager.DatacenterRackAwareActiveGossiper;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-
-public class StandAloneDatacenterAndRack {
-
-  public static void main (String [] args) throws UnknownHostException, InterruptedException {
-    GossipSettings s = new GossipSettings();
-    s.setWindowSize(1000);
-    s.setGossipInterval(100);
-    s.setActiveGossipClass(DatacenterRackAwareActiveGossiper.class.getName());
-    Map<String, String> gossipProps = new HashMap<>();
-    gossipProps.put("sameRackGossipIntervalMs", "2000");
-    gossipProps.put("differentDatacenterGossipIntervalMs", "10000");
-    s.setActiveGossipProperties(gossipProps);
-    Map<String, String> props = new HashMap<>();
-    props.put(DatacenterRackAwareActiveGossiper.DATACENTER, args[4]);
-    props.put(DatacenterRackAwareActiveGossiper.RACK, args[5]);
-    GossipManager manager = GossipManagerBuilder.newBuilder()
-            .cluster("mycluster")
-            .uri(URI.create(args[0]))
-            .id(args[1])
-            .gossipSettings(s)
-            .gossipMembers(Arrays.asList(new RemoteMember("mycluster", URI.create(args[2]), args[3])))
-            .properties(props)
-            .build();
-    manager.init();
-    while (true){
-      System.out.println("Live: " + manager.getLiveMembers());
-      System.out.println("Dead: " + manager.getDeadMembers());
-      Thread.sleep(2000);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/examples/StandAloneNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/examples/StandAloneNode.java b/src/main/java/org/apache/gossip/examples/StandAloneNode.java
deleted file mode 100644
index 93421b1..0000000
--- a/src/main/java/org/apache/gossip/examples/StandAloneNode.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.examples;
-
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import org.apache.gossip.GossipSettings;
-import org.apache.gossip.RemoteMember;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-
-public class StandAloneNode {
-  public static void main (String [] args) throws UnknownHostException, InterruptedException{
-    GossipSettings s = new GossipSettings();
-    s.setWindowSize(1000);
-    s.setGossipInterval(100);
-    GossipManager gossipService = GossipManagerBuilder.newBuilder()
-            .cluster("mycluster")
-            .uri(URI.create(args[0]))
-            .id(args[1])
-            .gossipMembers(Arrays.asList( new RemoteMember("mycluster", URI.create(args[2]), args[3])))
-            .gossipSettings(s)
-            .build();
-    gossipService.init();
-    while (true){
-      System.out.println("Live: " + gossipService.getLiveMembers());
-      System.out.println("Dead: " + gossipService.getDeadMembers());
-      Thread.sleep(2000);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java b/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
deleted file mode 100644
index d78cf5e..0000000
--- a/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
+++ /dev/null
@@ -1,115 +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.examples;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URI;
-import java.util.Arrays;
-import org.apache.gossip.GossipSettings;
-import org.apache.gossip.RemoteMember;
-import org.apache.gossip.crdt.GrowOnlyCounter;
-import org.apache.gossip.crdt.OrSet;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.GossipManagerBuilder;
-import org.apache.gossip.model.SharedDataMessage;
-
-public class StandAloneNodeCrdtOrSet {
-  public static void main (String [] args) throws InterruptedException, IOException{
-    GossipSettings s = new GossipSettings();
-    s.setWindowSize(1000);
-    s.setGossipInterval(100);
-    GossipManager gossipService = GossipManagerBuilder.newBuilder()
-            .cluster("mycluster")
-            .uri(URI.create(args[0]))
-            .id(args[1])
-            .gossipMembers(Arrays.asList( new RemoteMember("mycluster", URI.create(args[2]), args[3])))
-            .gossipSettings(s)
-            .build();
-    gossipService.init();
-    
-    new Thread(() -> {
-      while (true){
-      System.out.println("Live: " + gossipService.getLiveMembers());
-      System.out.println("Dead: " + gossipService.getDeadMembers());
-      System.out.println("---------- " + (gossipService.findCrdt("abc") == null ? "": 
-          gossipService.findCrdt("abc").value()));
-      System.out.println("********** " + gossipService.findCrdt("abc"));
-      System.out.println("^^^^^^^^^^ " + (gossipService.findCrdt("def") == null ? "": 
-        gossipService.findCrdt("def").value()));
-      System.out.println("$$$$$$$$$$ " + gossipService.findCrdt("def"));
-      try {
-        Thread.sleep(2000);
-      } catch (Exception e) {}
-      }
-    }).start();
-    
-    String line = null;
-    try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))){
-      while ( (line = br.readLine()) != null){
-        System.out.println(line);
-        char op = line.charAt(0);
-        String val = line.substring(2);
-        if (op == 'a'){
-          addData(val, gossipService);
-        } else if (op == 'r') {
-          removeData(val, gossipService);
-        } else if (op == 'g'){
-          gcount(val, gossipService);
-        }
-      }
-    }
-  }
-  
-  private static void gcount(String val, GossipManager gossipManager){
-    GrowOnlyCounter c = (GrowOnlyCounter) gossipManager.findCrdt("def");
-    Long l = Long.valueOf(val);
-    if (c == null){
-      c = new GrowOnlyCounter(new GrowOnlyCounter.Builder(gossipManager).increment((l)));
-    } else {
-      c = new GrowOnlyCounter(c, new GrowOnlyCounter.Builder(gossipManager).increment((l)));
-    }
-    SharedDataMessage m = new SharedDataMessage();
-    m.setExpireAt(Long.MAX_VALUE);
-    m.setKey("def");
-    m.setPayload(c);
-    m.setTimestamp(System.currentTimeMillis());
-    gossipManager.merge(m);
-  }
-  
-  private static void removeData(String val, GossipManager gossipService){
-    @SuppressWarnings("unchecked")
-    OrSet<String> s = (OrSet<String>) gossipService.findCrdt("abc");
-    SharedDataMessage m = new SharedDataMessage();
-    m.setExpireAt(Long.MAX_VALUE);
-    m.setKey("abc");
-    m.setPayload(new OrSet<String>(s , new OrSet.Builder<String>().remove(val)));
-    m.setTimestamp(System.currentTimeMillis());
-    gossipService.merge(m);
-  }
-  
-  private static void addData(String val, GossipManager gossipService){
-    SharedDataMessage m = new SharedDataMessage();
-    m.setExpireAt(Long.MAX_VALUE);
-    m.setKey("abc");
-    m.setPayload(new OrSet<String>(val));
-    m.setTimestamp(System.currentTimeMillis());
-    gossipService.merge(m);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java b/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java
deleted file mode 100644
index b73550e..0000000
--- a/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java
+++ /dev/null
@@ -1,171 +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.manager;
-
-import java.util.Map.Entry;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import com.codahale.metrics.Histogram;
-import com.codahale.metrics.MetricRegistry;
-import org.apache.gossip.LocalMember;
-import org.apache.gossip.model.ActiveGossipOk;
-import org.apache.gossip.model.PerNodeDataMessage;
-import org.apache.gossip.model.Member;
-import org.apache.gossip.model.Response;
-import org.apache.gossip.model.SharedDataMessage;
-import org.apache.gossip.model.ShutdownMessage;
-import org.apache.gossip.udp.UdpActiveGossipMessage;
-import org.apache.gossip.udp.UdpPerNodeDataMessage;
-import org.apache.gossip.udp.UdpSharedDataMessage;
-import org.apache.log4j.Logger;
-
-import static com.codahale.metrics.MetricRegistry.name;
-
-/**
- * The ActiveGossipThread is sends information. Pick a random partner and send the membership list to that partner
- */
-public abstract class AbstractActiveGossiper {
-
-  protected static final Logger LOGGER = Logger.getLogger(AbstractActiveGossiper.class);
-  
-  protected final GossipManager gossipManager;
-  protected final GossipCore gossipCore;
-  private final Histogram sharedDataHistogram;
-  private final Histogram sendPerNodeDataHistogram;
-  private final Histogram sendMembershipHistorgram;
-  private final Random random;
-
-  public AbstractActiveGossiper(GossipManager gossipManager, GossipCore gossipCore, MetricRegistry registry) {
-    this.gossipManager = gossipManager;
-    this.gossipCore = gossipCore;
-    sharedDataHistogram = registry.histogram(name(AbstractActiveGossiper.class, "sharedDataHistogram-time"));
-    sendPerNodeDataHistogram = registry.histogram(name(AbstractActiveGossiper.class, "sendPerNodeDataHistogram-time"));
-    sendMembershipHistorgram = registry.histogram(name(AbstractActiveGossiper.class, "sendMembershipHistorgram-time"));
-    random = new Random();
-  }
-
-  public void init() {
-
-  }
-  
-  public void shutdown() {
-
-  }
-
-  public final void sendShutdownMessage(LocalMember me, LocalMember target){
-    if (target == null){
-      return;
-    }
-    ShutdownMessage m = new ShutdownMessage();
-    m.setNodeId(me.getId());
-    m.setShutdownAtNanos(gossipManager.getClock().nanoTime());
-    gossipCore.sendOneWay(m, target.getUri());
-  }
-  
-  public final void sendSharedData(LocalMember me, LocalMember member){
-    if (member == null){
-      return;
-    }
-    long startTime = System.currentTimeMillis();
-    for (Entry<String, SharedDataMessage> innerEntry : gossipCore.getSharedData().entrySet()){
-      UdpSharedDataMessage message = new UdpSharedDataMessage();
-      message.setUuid(UUID.randomUUID().toString());
-      message.setUriFrom(me.getId());
-      message.setExpireAt(innerEntry.getValue().getExpireAt());
-      message.setKey(innerEntry.getValue().getKey());
-      message.setNodeId(innerEntry.getValue().getNodeId());
-      message.setTimestamp(innerEntry.getValue().getTimestamp());
-      message.setPayload(innerEntry.getValue().getPayload());
-      gossipCore.sendOneWay(message, member.getUri());
-    }
-    sharedDataHistogram.update(System.currentTimeMillis() - startTime);
-  }
-  
-  public final void sendPerNodeData(LocalMember me, LocalMember member){
-    if (member == null){
-      return;
-    }
-    long startTime = System.currentTimeMillis();
-    for (Entry<String, ConcurrentHashMap<String, PerNodeDataMessage>> entry : gossipCore.getPerNodeData().entrySet()){
-      for (Entry<String, PerNodeDataMessage> innerEntry : entry.getValue().entrySet()){
-        UdpPerNodeDataMessage message = new UdpPerNodeDataMessage();
-        message.setUuid(UUID.randomUUID().toString());
-        message.setUriFrom(me.getId());
-        message.setExpireAt(innerEntry.getValue().getExpireAt());
-        message.setKey(innerEntry.getValue().getKey());
-        message.setNodeId(innerEntry.getValue().getNodeId());
-        message.setTimestamp(innerEntry.getValue().getTimestamp());
-        message.setPayload(innerEntry.getValue().getPayload());
-        gossipCore.sendOneWay(message, member.getUri());   
-      }
-    }
-    sendPerNodeDataHistogram.update(System.currentTimeMillis() - startTime);
-  }
-    
-  /**
-   * Performs the sending of the membership list, after we have incremented our own heartbeat.
-   */
-  protected void sendMembershipList(LocalMember me, LocalMember member) {
-    if (member == null){
-      return;
-    }
-    long startTime = System.currentTimeMillis();
-    me.setHeartbeat(System.nanoTime());
-    UdpActiveGossipMessage message = new UdpActiveGossipMessage();
-    message.setUriFrom(gossipManager.getMyself().getUri().toASCIIString());
-    message.setUuid(UUID.randomUUID().toString());
-    message.getMembers().add(convert(me));
-    for (LocalMember other : gossipManager.getMembers().keySet()) {
-      message.getMembers().add(convert(other));
-    }
-    Response r = gossipCore.send(message, member.getUri());
-    if (r instanceof ActiveGossipOk){
-      //maybe count metrics here
-    } else {
-      LOGGER.debug("Message " + message + " generated response " + r);
-    }
-    sendMembershipHistorgram.update(System.currentTimeMillis() - startTime);
-  }
-    
-  protected final Member convert(LocalMember member){
-    Member gm = new Member();
-    gm.setCluster(member.getClusterName());
-    gm.setHeartbeat(member.getHeartbeat());
-    gm.setUri(member.getUri().toASCIIString());
-    gm.setId(member.getId());
-    gm.setProperties(member.getProperties());
-    return gm;
-  }
-  
-  /**
-   * 
-   * @param memberList
-   *          An immutable list
-   * @return The chosen LocalGossipMember to gossip with.
-   */
-  protected LocalMember selectPartner(List<LocalMember> memberList) {
-    LocalMember member = null;
-    if (memberList.size() > 0) {
-      int randomNeighborIndex = random.nextInt(memberList.size());
-      member = memberList.get(randomNeighborIndex);
-    }
-    return member;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/Clock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/Clock.java b/src/main/java/org/apache/gossip/manager/Clock.java
deleted file mode 100644
index 6629c62..0000000
--- a/src/main/java/org/apache/gossip/manager/Clock.java
+++ /dev/null
@@ -1,25 +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.manager;
-
-public interface Clock {
-
-  long currentTimeMillis();
-  long nanoTime();
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/DataReaper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/DataReaper.java b/src/main/java/org/apache/gossip/manager/DataReaper.java
deleted file mode 100644
index 8175a1b..0000000
--- a/src/main/java/org/apache/gossip/manager/DataReaper.java
+++ /dev/null
@@ -1,85 +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.manager;
-
-import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.gossip.model.PerNodeDataMessage;
-import org.apache.gossip.model.SharedDataMessage;
-
-/**
- * We wish to periodically sweep user data and remove entries past their timestamp. This
- * implementation periodically sweeps through the data and removes old entries. While it might make
- * sense to use a more specific high performance data-structure to handle eviction, keep in mind
- * that we are not looking to store a large quantity of data as we currently have to transmit this
- * data cluster wide.
- */
-public class DataReaper {
-
-  private final GossipCore gossipCore;
-  private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);
-  private final Clock clock;
-  
-  public DataReaper(GossipCore gossipCore, Clock clock){
-    this.gossipCore = gossipCore;
-    this.clock = clock;
-  }
-  
-  public void init(){
-    Runnable reapPerNodeData = () -> {
-      runPerNodeOnce();
-      runSharedOnce();
-    };
-    scheduledExecutor.scheduleAtFixedRate(reapPerNodeData, 0, 5, TimeUnit.SECONDS);
-  }
-  
-  void runSharedOnce(){
-    for (Entry<String, SharedDataMessage> entry : gossipCore.getSharedData().entrySet()){
-      if (entry.getValue().getExpireAt() < clock.currentTimeMillis()){
-        gossipCore.getSharedData().remove(entry.getKey(), entry.getValue());
-      }
-    }
-  }
-  
-  void runPerNodeOnce(){
-    for (Entry<String, ConcurrentHashMap<String, PerNodeDataMessage>> node : gossipCore.getPerNodeData().entrySet()){
-      reapData(node.getValue());
-    }
-  }
-  
-  void reapData(ConcurrentHashMap<String, PerNodeDataMessage> concurrentHashMap){
-    for (Entry<String, PerNodeDataMessage> entry : concurrentHashMap.entrySet()){
-      if (entry.getValue().getExpireAt() < clock.currentTimeMillis()){
-        concurrentHashMap.remove(entry.getKey(), entry.getValue());
-      }
-    }
-  }
-  
-  public void close(){
-    scheduledExecutor.shutdown();
-    try {
-      scheduledExecutor.awaitTermination(1, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java b/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java
deleted file mode 100644
index 2f489a2..0000000
--- a/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java
+++ /dev/null
@@ -1,244 +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.manager;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.gossip.LocalMember;
-
-import com.codahale.metrics.MetricRegistry;
-
-/**
- * Sends gossip traffic at different rates to other racks and data-centers.
- * This implementation controls the rate at which gossip traffic is shared. 
- * There are two constructs Datacenter and Rack. It is assumed that bandwidth and latency is higher
- * in the rack than in the the datacenter. We can adjust the rate at which we send messages to each group.
- * 
- */
-public class DatacenterRackAwareActiveGossiper extends AbstractActiveGossiper {
-
-  public static final String DATACENTER = "datacenter";
-  public static final String RACK = "rack";
-  
-  private int sameRackGossipIntervalMs = 100;
-  private int sameDcGossipIntervalMs = 500;
-  private int differentDatacenterGossipIntervalMs = 1000;
-  private int randomDeadMemberSendIntervalMs = 250;
-  
-  private ScheduledExecutorService scheduledExecutorService;
-  private final BlockingQueue<Runnable> workQueue;
-  private ThreadPoolExecutor threadService;
-  
-  public DatacenterRackAwareActiveGossiper(GossipManager gossipManager, GossipCore gossipCore,
-          MetricRegistry registry) {
-    super(gossipManager, gossipCore, registry);
-    scheduledExecutorService = Executors.newScheduledThreadPool(2);
-    workQueue = new ArrayBlockingQueue<Runnable>(1024);
-    threadService = new ThreadPoolExecutor(1, 30, 1, TimeUnit.SECONDS, workQueue,
-            new ThreadPoolExecutor.DiscardOldestPolicy());
-    try {
-      sameRackGossipIntervalMs = Integer.parseInt(gossipManager.getSettings()
-              .getActiveGossipProperties().get("sameRackGossipIntervalMs"));
-    } catch (RuntimeException ex) { }
-    try {
-      sameDcGossipIntervalMs = Integer.parseInt(gossipManager.getSettings()
-              .getActiveGossipProperties().get("sameDcGossipIntervalMs"));
-    } catch (RuntimeException ex) { }
-    try {
-      differentDatacenterGossipIntervalMs = Integer.parseInt(gossipManager.getSettings()
-              .getActiveGossipProperties().get("differentDatacenterGossipIntervalMs"));
-    } catch (RuntimeException ex) { }
-    try {
-      randomDeadMemberSendIntervalMs = Integer.parseInt(gossipManager.getSettings()
-              .getActiveGossipProperties().get("randomDeadMemberSendIntervalMs"));
-    } catch (RuntimeException ex) { }
-  }
-
-  @Override
-  public void init() {
-    super.init();
-    //same rack
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-      threadService.execute(() -> sendToSameRackMember()), 
-      0, sameRackGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-      threadService.execute(() -> sendToSameRackMemberPerNode()), 
-      0, sameRackGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-      threadService.execute(() -> sendToSameRackShared()), 
-      0, sameRackGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    //same dc different rack
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-      threadService.execute(() -> sameDcDiffernetRackMember()), 
-      0, sameDcGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-    threadService.execute(() -> sameDcDiffernetRackPerNode()), 
-    0, sameDcGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-    threadService.execute(() -> sameDcDiffernetRackShared()), 
-    0, sameDcGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    //different dc
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-      threadService.execute(() -> differentDcMember()), 
-      0, differentDatacenterGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-    threadService.execute(() -> differentDcPerNode()), 
-    0, differentDatacenterGossipIntervalMs, TimeUnit.MILLISECONDS);
-  
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-    threadService.execute(() -> differentDcShared()), 
-    0, differentDatacenterGossipIntervalMs, TimeUnit.MILLISECONDS);
-    
-    //the dead
-    scheduledExecutorService.scheduleAtFixedRate(() -> 
-      threadService.execute(() -> sendToDeadMember()), 
-      0, randomDeadMemberSendIntervalMs, TimeUnit.MILLISECONDS);
-    
-  }
-
-  private void sendToDeadMember() {
-    sendMembershipList(gossipManager.getMyself(), selectPartner(gossipManager.getDeadMembers()));
-  }
-  
-  private List<LocalMember> differentDataCenter(){
-    String myDc = gossipManager.getMyself().getProperties().get(DATACENTER);
-    String rack = gossipManager.getMyself().getProperties().get(RACK);
-    if (myDc == null|| rack == null){
-      return Collections.emptyList();
-    }
-    List<LocalMember> notMyDc = new ArrayList<LocalMember>(10);
-    for (LocalMember i : gossipManager.getLiveMembers()){
-      if (!myDc.equals(i.getProperties().get(DATACENTER))){
-        notMyDc.add(i);
-      }
-    }
-    return notMyDc;
-  }
-  
-  private List<LocalMember> sameDatacenterDifferentRack(){
-    String myDc = gossipManager.getMyself().getProperties().get(DATACENTER);
-    String rack = gossipManager.getMyself().getProperties().get(RACK);
-    if (myDc == null|| rack == null){
-      return Collections.emptyList();
-    }
-    List<LocalMember> notMyDc = new ArrayList<LocalMember>(10);
-    for (LocalMember i : gossipManager.getLiveMembers()){
-      if (myDc.equals(i.getProperties().get(DATACENTER)) && !rack.equals(i.getProperties().get(RACK))){
-        notMyDc.add(i);
-      }
-    }
-    return notMyDc;
-  }
-    
-  private List<LocalMember> sameRackNodes(){
-    String myDc = gossipManager.getMyself().getProperties().get(DATACENTER);
-    String rack = gossipManager.getMyself().getProperties().get(RACK);
-    if (myDc == null|| rack == null){
-      return Collections.emptyList();
-    }
-    List<LocalMember> sameDcAndRack = new ArrayList<LocalMember>(10);
-    for (LocalMember i : gossipManager.getLiveMembers()){
-      if (myDc.equals(i.getProperties().get(DATACENTER))
-              && rack.equals(i.getProperties().get(RACK))){
-        sameDcAndRack.add(i);
-      }
-    }
-    return sameDcAndRack;
-  }
-
-  private void sendToSameRackMember() {
-    LocalMember i = selectPartner(sameRackNodes());
-    sendMembershipList(gossipManager.getMyself(), i);
-  }
-  
-  private void sendToSameRackMemberPerNode() {
-    sendPerNodeData(gossipManager.getMyself(), selectPartner(sameRackNodes()));
-  }
-  
-  private void sendToSameRackShared() {
-    sendSharedData(gossipManager.getMyself(), selectPartner(sameRackNodes()));
-  }
-  
-  private void differentDcMember() {
-    sendMembershipList(gossipManager.getMyself(), selectPartner(differentDataCenter()));
-  }
-  
-  private void differentDcPerNode() {
-    sendPerNodeData(gossipManager.getMyself(), selectPartner(differentDataCenter()));
-  }
-  
-  private void differentDcShared() {
-    sendSharedData(gossipManager.getMyself(), selectPartner(differentDataCenter()));
-  }
-  
-  private void sameDcDiffernetRackMember() {
-    sendMembershipList(gossipManager.getMyself(), selectPartner(sameDatacenterDifferentRack()));
-  }
-  
-  private void sameDcDiffernetRackPerNode() {
-    sendPerNodeData(gossipManager.getMyself(), selectPartner(sameDatacenterDifferentRack()));
-  }
-  
-  private void sameDcDiffernetRackShared() {
-    sendSharedData(gossipManager.getMyself(), selectPartner(sameDatacenterDifferentRack()));
-  }
-  
-  @Override
-  public void shutdown() {
-    super.shutdown();
-    scheduledExecutorService.shutdown();
-    try {
-      scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      LOGGER.debug("Issue during shutdown", e);
-    }
-    sendShutdownMessage();
-    threadService.shutdown();
-    try {
-      threadService.awaitTermination(5, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      LOGGER.debug("Issue during shutdown", e);
-    }
-  }
-  
-  /**
-   * sends an optimistic shutdown message to several clusters nodes
-   */
-  protected void sendShutdownMessage(){
-    List<LocalMember> l = gossipManager.getLiveMembers();
-    int sendTo = l.size() < 3 ? 1 : l.size() / 3;
-    for (int i = 0; i < sendTo; i++) {
-      threadService.execute(() -> sendShutdownMessage(gossipManager.getMyself(), selectPartner(l)));
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/GossipCore.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/GossipCore.java b/src/main/java/org/apache/gossip/manager/GossipCore.java
deleted file mode 100644
index f53419d..0000000
--- a/src/main/java/org/apache/gossip/manager/GossipCore.java
+++ /dev/null
@@ -1,387 +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.manager;
-
-import com.codahale.metrics.Gauge;
-import com.codahale.metrics.Meter;
-import com.codahale.metrics.MetricRegistry;
-import org.apache.gossip.Member;
-import org.apache.gossip.LocalMember;
-import org.apache.gossip.RemoteMember;
-import org.apache.gossip.crdt.Crdt;
-import org.apache.gossip.event.GossipState;
-import org.apache.gossip.model.*;
-import org.apache.gossip.udp.Trackable;
-import org.apache.log4j.Logger;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.URI;
-import java.security.*;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.concurrent.*;
-
-public class GossipCore implements GossipCoreConstants {
-
-  class LatchAndBase {
-    private final CountDownLatch latch;
-    private volatile Base base;
-    
-    LatchAndBase(){
-      latch = new CountDownLatch(1);
-    }
-    
-  }
-  public static final Logger LOGGER = Logger.getLogger(GossipCore.class);
-  private final GossipManager gossipManager;
-  private ConcurrentHashMap<String, LatchAndBase> requests;
-  private ThreadPoolExecutor service;
-  private final ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> perNodeData;
-  private final ConcurrentHashMap<String, SharedDataMessage> sharedData;
-  private final BlockingQueue<Runnable> workQueue;
-  private final PKCS8EncodedKeySpec privKeySpec;
-  private final PrivateKey privKey;
-  private final Meter messageSerdeException;
-  private final Meter tranmissionException;
-  private final Meter tranmissionSuccess;
-
-  public GossipCore(GossipManager manager, MetricRegistry metrics){
-    this.gossipManager = manager;
-    requests = new ConcurrentHashMap<>();
-    workQueue = new ArrayBlockingQueue<>(1024);
-    service = new ThreadPoolExecutor(1, 5, 1, TimeUnit.SECONDS, workQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
-    perNodeData = new ConcurrentHashMap<>();
-    sharedData = new ConcurrentHashMap<>();
-    metrics.register(WORKQUEUE_SIZE, (Gauge<Integer>)() -> workQueue.size());
-    metrics.register(PER_NODE_DATA_SIZE, (Gauge<Integer>)() -> perNodeData.size());
-    metrics.register(SHARED_DATA_SIZE, (Gauge<Integer>)() ->  sharedData.size());
-    metrics.register(REQUEST_SIZE, (Gauge<Integer>)() ->  requests.size());
-    metrics.register(THREADPOOL_ACTIVE, (Gauge<Integer>)() ->  service.getActiveCount());
-    metrics.register(THREADPOOL_SIZE, (Gauge<Integer>)() ->  service.getPoolSize());
-    messageSerdeException = metrics.meter(MESSAGE_SERDE_EXCEPTION);
-    tranmissionException = metrics.meter(MESSAGE_TRANSMISSION_EXCEPTION);
-    tranmissionSuccess = metrics.meter(MESSAGE_TRANSMISSION_SUCCESS);
-
-    if (manager.getSettings().isSignMessages()){
-      File privateKey = new File(manager.getSettings().getPathToKeyStore(), manager.getMyself().getId());
-      File publicKey = new File(manager.getSettings().getPathToKeyStore(), manager.getMyself().getId() + ".pub");
-      if (!privateKey.exists()){
-        throw new IllegalArgumentException("private key not found " + privateKey);
-      }
-      if (!publicKey.exists()){
-        throw new IllegalArgumentException("public key not found " + publicKey);
-      }
-      try (FileInputStream keyfis = new FileInputStream(privateKey)) {
-        byte[] encKey = new byte[keyfis.available()];
-        keyfis.read(encKey);
-        keyfis.close();
-        privKeySpec = new PKCS8EncodedKeySpec(encKey);
-        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
-        privKey = keyFactory.generatePrivate(privKeySpec);
-      } catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {
-        throw new RuntimeException("failed hard", e);
-      }
-    } else {
-      privKeySpec = null;
-      privKey = null;
-    }
-  }
-
-  private byte [] sign(byte [] bytes){
-    Signature dsa;
-    try {
-      dsa = Signature.getInstance("SHA1withDSA", "SUN");
-      dsa.initSign(privKey);
-      dsa.update(bytes);
-      return dsa.sign();
-    } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | SignatureException e) {
-      throw new RuntimeException(e);
-    } 
-  }
-
-  @SuppressWarnings({ "unchecked", "rawtypes" })
-  public void addSharedData(SharedDataMessage message) {
-    while (true){
-      SharedDataMessage previous = sharedData.putIfAbsent(message.getKey(), message);
-      if (previous == null){
-        return;
-      }
-      if (message.getPayload() instanceof Crdt){
-        SharedDataMessage merged = new SharedDataMessage();
-        merged.setExpireAt(message.getExpireAt());
-        merged.setKey(message.getKey());
-        merged.setNodeId(message.getNodeId());
-        merged.setTimestamp(message.getTimestamp());
-        Crdt mergedCrdt = ((Crdt) previous.getPayload()).merge((Crdt) message.getPayload());
-        merged.setPayload(mergedCrdt);
-        boolean replaced = sharedData.replace(message.getKey(), previous, merged);
-        if (replaced){
-          return;
-        }
-      } else {
-        if (previous.getTimestamp() < message.getTimestamp()){
-          boolean result = sharedData.replace(message.getKey(), previous, message);
-          if (result){
-            return;
-          }
-        } else {
-          return;
-        }
-      }
-    }
-  }
-  
-  public void addPerNodeData(PerNodeDataMessage message){
-    ConcurrentHashMap<String,PerNodeDataMessage> nodeMap = new ConcurrentHashMap<>();
-    nodeMap.put(message.getKey(), message);
-    nodeMap = perNodeData.putIfAbsent(message.getNodeId(), nodeMap);
-    if (nodeMap != null){
-      PerNodeDataMessage current = nodeMap.get(message.getKey());
-      if (current == null){
-        nodeMap.putIfAbsent(message.getKey(), message);
-      } else {
-        if (current.getTimestamp() < message.getTimestamp()){
-          nodeMap.replace(message.getKey(), current, message);
-        }
-      }
-    }
-  }
-
-  public ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> getPerNodeData(){
-    return perNodeData;
-  }
-
-  public ConcurrentHashMap<String, SharedDataMessage> getSharedData() {
-    return sharedData;
-  }
-
-  public void shutdown(){
-    service.shutdown();
-    try {
-      service.awaitTermination(1, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      LOGGER.warn(e);
-    }
-    service.shutdownNow();
-  }
-
-  public void receive(Base base) {
-    if (!gossipManager.getMessageInvoker().invoke(this, gossipManager, base)) {
-      LOGGER.warn("received message can not be handled");
-    }
-  }
-
-  /**
-   * Sends a blocking message.
-   * @param message
-   * @param uri
-   * @throws RuntimeException if data can not be serialized or in transmission error
-   */
-  private void sendInternal(Base message, URI uri){
-    byte[] json_bytes;
-    try {
-      if (privKey == null){
-        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(message);
-      } else {
-        SignedPayload p = new SignedPayload();
-        p.setData(gossipManager.getObjectMapper().writeValueAsString(message).getBytes());
-        p.setSignature(sign(p.getData()));
-        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(p);
-      }
-    } catch (IOException e) {
-      messageSerdeException.mark();
-      throw new RuntimeException(e);
-    }
-    try (DatagramSocket socket = new DatagramSocket()) {
-      socket.setSoTimeout(gossipManager.getSettings().getGossipInterval() * 2);
-      InetAddress dest = InetAddress.getByName(uri.getHost());
-      DatagramPacket datagramPacket = new DatagramPacket(json_bytes, json_bytes.length, dest, uri.getPort());
-      socket.send(datagramPacket);
-      tranmissionSuccess.mark();
-    } catch (IOException e) {
-      tranmissionException.mark();
-      throw new RuntimeException(e);
-    }
-  }
-
-  public Response send(Base message, URI uri){
-    if (LOGGER.isDebugEnabled()){
-      LOGGER.debug("Sending " + message);
-      LOGGER.debug("Current request queue " + requests);
-    }
-
-    final Trackable t;
-    LatchAndBase latchAndBase = null;
-    if (message instanceof Trackable){
-      t = (Trackable) message;
-      latchAndBase = new LatchAndBase();
-      requests.put(t.getUuid() + "/" + t.getUriFrom(), latchAndBase);
-    } else {
-      t = null;
-    }
-    sendInternal(message, uri);
-    if (latchAndBase == null){
-      return null;
-    } 
-    
-    try {
-      boolean complete = latchAndBase.latch.await(1, TimeUnit.SECONDS);
-      if (complete){
-        return (Response) latchAndBase.base;
-      } else{
-        return null;
-      }
-    } catch (InterruptedException e) {
-      throw new RuntimeException(e);
-    } finally {
-      if (latchAndBase != null){
-        requests.remove(t.getUuid() + "/" + t.getUriFrom());
-      }
-    }
-  }
-
-  /**
-   * Sends a message across the network while blocking. Catches and ignores IOException in transmission. Used
-   * when the protocol for the message is not to wait for a response
-   * @param message the message to send
-   * @param u the uri to send it to
-   */
-  public void sendOneWay(Base message, URI u){
-    byte[] json_bytes;
-    try {
-      if (privKey == null){
-        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(message);
-      } else {
-        SignedPayload p = new SignedPayload();
-        p.setData(gossipManager.getObjectMapper().writeValueAsString(message).getBytes());
-        p.setSignature(sign(p.getData()));
-        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(p);
-      }
-    } catch (IOException e) {
-      messageSerdeException.mark();
-      throw new RuntimeException(e);
-    }
-    try (DatagramSocket socket = new DatagramSocket()) {
-      socket.setSoTimeout(gossipManager.getSettings().getGossipInterval() * 2);
-      InetAddress dest = InetAddress.getByName(u.getHost());
-      DatagramPacket datagramPacket = new DatagramPacket(json_bytes, json_bytes.length, dest, u.getPort());
-      socket.send(datagramPacket);
-      tranmissionSuccess.mark();
-    } catch (IOException ex) {
-      tranmissionException.mark();
-      LOGGER.debug("Send one way failed", ex);
-    }
-  }
-
-  public void handleResponse(String k, Base v) {
-    LatchAndBase latch = requests.get(k);
-    latch.base = v;
-    latch.latch.countDown();
-  }
-
-  /**
-   * Merge lists from remote members and update heartbeats
-   *
-   * @param gossipManager
-   * @param senderMember
-   * @param remoteList
-   *
-   */
-  public void mergeLists(GossipManager gossipManager, RemoteMember senderMember,
-          List<Member> remoteList) {
-    if (LOGGER.isDebugEnabled()){
-      debugState(senderMember, remoteList);
-    }
-    for (LocalMember i : gossipManager.getDeadMembers()) {
-      if (i.getId().equals(senderMember.getId())) {
-        LOGGER.debug(gossipManager.getMyself() + " contacted by dead member " + senderMember.getUri());
-        i.recordHeartbeat(senderMember.getHeartbeat());
-        i.setHeartbeat(senderMember.getHeartbeat());
-        //TODO consider forcing an UP here
-      }
-    }
-    for (Member remoteMember : remoteList) {
-      if (remoteMember.getId().equals(gossipManager.getMyself().getId())) {
-        continue;
-      }
-      LocalMember aNewMember = new LocalMember(remoteMember.getClusterName(),
-      remoteMember.getUri(),
-      remoteMember.getId(),
-      remoteMember.getHeartbeat(),
-      remoteMember.getProperties(),
-      gossipManager.getSettings().getWindowSize(),
-      gossipManager.getSettings().getMinimumSamples(),
-      gossipManager.getSettings().getDistribution());
-      aNewMember.recordHeartbeat(remoteMember.getHeartbeat());
-      Object result = gossipManager.getMembers().putIfAbsent(aNewMember, GossipState.UP);
-      if (result != null){
-        for (Entry<LocalMember, GossipState> localMember : gossipManager.getMembers().entrySet()){
-          if (localMember.getKey().getId().equals(remoteMember.getId())){
-            localMember.getKey().recordHeartbeat(remoteMember.getHeartbeat());
-            localMember.getKey().setHeartbeat(remoteMember.getHeartbeat());
-            localMember.getKey().setProperties(remoteMember.getProperties());
-          }
-        }
-      }
-    }
-    if (LOGGER.isDebugEnabled()){
-      debugState(senderMember, remoteList);
-    }
-  }
-
-  private void debugState(RemoteMember senderMember,
-          List<Member> remoteList){
-    LOGGER.warn(
-          "-----------------------\n" +
-          "Me " + gossipManager.getMyself() + "\n" +
-          "Sender " + senderMember + "\n" +
-          "RemoteList " + remoteList + "\n" +
-          "Live " + gossipManager.getLiveMembers()+ "\n" +
-          "Dead " + gossipManager.getDeadMembers()+ "\n" +
-          "=======================");
-  }
-
-  @SuppressWarnings("rawtypes")
-  public Crdt merge(SharedDataMessage message) {
-    for (;;){
-      SharedDataMessage previous = sharedData.putIfAbsent(message.getKey(), message);
-      if (previous == null){
-        return (Crdt) message.getPayload();
-      }
-      SharedDataMessage copy = new SharedDataMessage();
-      copy.setExpireAt(message.getExpireAt());
-      copy.setKey(message.getKey());
-      copy.setNodeId(message.getNodeId());
-      copy.setTimestamp(message.getTimestamp());
-      @SuppressWarnings("unchecked")
-      Crdt merged = ((Crdt) previous.getPayload()).merge((Crdt) message.getPayload());
-      copy.setPayload(merged);
-      boolean replaced = sharedData.replace(message.getKey(), previous, copy);
-      if (replaced){
-        return merged;
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java b/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java
deleted file mode 100644
index 6d3765a..0000000
--- a/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java
+++ /dev/null
@@ -1,30 +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.manager;
-
-public interface GossipCoreConstants {
-  String WORKQUEUE_SIZE = "gossip.core.workqueue.size";
-  String PER_NODE_DATA_SIZE = "gossip.core.pernodedata.size"; 
-  String SHARED_DATA_SIZE = "gossip.core.shareddata.size";
-  String REQUEST_SIZE = "gossip.core.requests.size";
-  String THREADPOOL_ACTIVE = "gossip.core.threadpool.active";
-  String THREADPOOL_SIZE = "gossip.core.threadpool.size";
-  String MESSAGE_SERDE_EXCEPTION = "gossip.core.message_serde_exception";
-  String MESSAGE_TRANSMISSION_EXCEPTION = "gossip.core.message_transmission_exception";
-  String MESSAGE_TRANSMISSION_SUCCESS = "gossip.core.message_transmission_success";
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/GossipManager.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/GossipManager.java b/src/main/java/org/apache/gossip/manager/GossipManager.java
deleted file mode 100644
index c2b50ae..0000000
--- a/src/main/java/org/apache/gossip/manager/GossipManager.java
+++ /dev/null
@@ -1,319 +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.manager;
-
-import com.codahale.metrics.MetricRegistry;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.gossip.GossipSettings;
-import org.apache.gossip.LocalMember;
-import org.apache.gossip.Member;
-import org.apache.gossip.crdt.Crdt;
-import org.apache.gossip.event.GossipListener;
-import org.apache.gossip.event.GossipState;
-import org.apache.gossip.manager.handlers.MessageInvoker;
-import org.apache.gossip.manager.impl.OnlyProcessReceivedPassiveGossipThread;
-import org.apache.gossip.model.PerNodeDataMessage;
-import org.apache.gossip.model.SharedDataMessage;
-import org.apache.log4j.Logger;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-
-public abstract class GossipManager {
-
-  public static final Logger LOGGER = Logger.getLogger(GossipManager.class);
-
-  private final ConcurrentSkipListMap<LocalMember, GossipState> members;
-  private final LocalMember me;
-  private final GossipSettings settings;
-  private final AtomicBoolean gossipServiceRunning;
-  private AbstractActiveGossiper activeGossipThread;
-  private PassiveGossipThread passiveGossipThread;
-  private ExecutorService gossipThreadExecutor;
-  private final GossipCore gossipCore;
-  private final DataReaper dataReaper;
-  private final Clock clock;
-  private final ScheduledExecutorService scheduledServiced;
-  private final MetricRegistry registry;
-  private final RingStatePersister ringState;
-  private final UserDataPersister userDataState;
-  private final GossipMemberStateRefresher memberStateRefresher;
-  private final ObjectMapper objectMapper;
-
-  private final MessageInvoker messageInvoker;
-
-  public GossipManager(String cluster,
-                       URI uri, String id, Map<String, String> properties, GossipSettings settings,
-                       List<Member> gossipMembers, GossipListener listener, MetricRegistry registry,
-                       ObjectMapper objectMapper, MessageInvoker messageInvoker) {
-    this.settings = settings;
-    this.messageInvoker = messageInvoker;
-
-    clock = new SystemClock();
-    me = new LocalMember(cluster, uri, id, clock.nanoTime(), properties,
-            settings.getWindowSize(), settings.getMinimumSamples(), settings.getDistribution());
-    gossipCore = new GossipCore(this, registry);
-    dataReaper = new DataReaper(gossipCore, clock);
-    members = new ConcurrentSkipListMap<>();
-    for (Member startupMember : gossipMembers) {
-      if (!startupMember.equals(me)) {
-        LocalMember member = new LocalMember(startupMember.getClusterName(),
-                startupMember.getUri(), startupMember.getId(),
-                clock.nanoTime(), startupMember.getProperties(), settings.getWindowSize(),
-                settings.getMinimumSamples(), settings.getDistribution());
-        //TODO should members start in down state?
-        members.put(member, GossipState.DOWN);
-      }
-    }
-    gossipThreadExecutor = Executors.newCachedThreadPool();
-    gossipServiceRunning = new AtomicBoolean(true);
-    this.scheduledServiced = Executors.newScheduledThreadPool(1);
-    this.registry = registry;
-    this.ringState = new RingStatePersister(this);
-    this.userDataState = new UserDataPersister(this, this.gossipCore);
-    this.memberStateRefresher = new GossipMemberStateRefresher(members, settings, listener, this::findPerNodeGossipData);
-    this.objectMapper = objectMapper;
-    readSavedRingState();
-    readSavedDataState();
-  }
-
-  public MessageInvoker getMessageInvoker() {
-    return messageInvoker;
-  }
-
-  public ConcurrentSkipListMap<LocalMember, GossipState> getMembers() {
-    return members;
-  }
-
-  public GossipSettings getSettings() {
-    return settings;
-  }
-
-  /**
-   * @return a read only list of members found in the DOWN state.
-   */
-  public List<LocalMember> getDeadMembers() {
-    return Collections.unmodifiableList(
-            members.entrySet()
-                    .stream()
-                    .filter(entry -> GossipState.DOWN.equals(entry.getValue()))
-                    .map(Entry::getKey).collect(Collectors.toList()));
-  }
-
-  /**
-   *
-   * @return a read only list of members found in the UP state
-   */
-  public List<LocalMember> getLiveMembers() {
-    return Collections.unmodifiableList(
-            members.entrySet()
-                    .stream()
-                    .filter(entry -> GossipState.UP.equals(entry.getValue()))
-                    .map(Entry::getKey).collect(Collectors.toList()));
-  }
-
-  public LocalMember getMyself() {
-    return me;
-  }
-
-  private AbstractActiveGossiper constructActiveGossiper(){
-    try {
-      Constructor<?> c = Class.forName(settings.getActiveGossipClass()).getConstructor(GossipManager.class, GossipCore.class, MetricRegistry.class);
-      return (AbstractActiveGossiper) c.newInstance(this, gossipCore, registry);
-    } catch (NoSuchMethodException | SecurityException | ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Starts the client. Specifically, start the various cycles for this protocol. Start the gossip
-   * thread and start the receiver thread.
-   */
-  public void init() {
-    passiveGossipThread = new OnlyProcessReceivedPassiveGossipThread(this, gossipCore);
-    gossipThreadExecutor.execute(passiveGossipThread);
-    activeGossipThread = constructActiveGossiper();
-    activeGossipThread.init();
-    dataReaper.init();
-    scheduledServiced.scheduleAtFixedRate(ringState, 60, 60, TimeUnit.SECONDS);
-    scheduledServiced.scheduleAtFixedRate(userDataState, 60, 60, TimeUnit.SECONDS);
-    scheduledServiced.scheduleAtFixedRate(memberStateRefresher, 0, 100, TimeUnit.MILLISECONDS);
-    LOGGER.debug("The GossipManager is started.");
-  }
-
-  private void readSavedRingState() {
-    for (LocalMember l : ringState.readFromDisk()){
-      LocalMember member = new LocalMember(l.getClusterName(),
-              l.getUri(), l.getId(),
-              clock.nanoTime(), l.getProperties(), settings.getWindowSize(),
-              settings.getMinimumSamples(), settings.getDistribution());
-      members.putIfAbsent(member, GossipState.DOWN);
-    }
-  }
-
-  private void readSavedDataState() {
-    for (Entry<String, ConcurrentHashMap<String, PerNodeDataMessage>> l : userDataState.readPerNodeFromDisk().entrySet()){
-      for (Entry<String, PerNodeDataMessage> j : l.getValue().entrySet()){
-        gossipCore.addPerNodeData(j.getValue());
-      }
-    }
-    for (Entry<String, SharedDataMessage> l: userDataState.readSharedDataFromDisk().entrySet()){
-      gossipCore.addSharedData(l.getValue());
-    }
-  }
-
-  /**
-   * Shutdown the gossip service.
-   */
-  public void shutdown() {
-    gossipServiceRunning.set(false);
-    gossipThreadExecutor.shutdown();
-    gossipCore.shutdown();
-    dataReaper.close();
-    if (passiveGossipThread != null) {
-      passiveGossipThread.shutdown();
-    }
-    if (activeGossipThread != null) {
-      activeGossipThread.shutdown();
-    }
-    try {
-      boolean result = gossipThreadExecutor.awaitTermination(10, TimeUnit.MILLISECONDS);
-      if (!result) {
-        LOGGER.error("executor shutdown timed out");
-      }
-    } catch (InterruptedException e) {
-      LOGGER.error(e);
-    }
-    gossipThreadExecutor.shutdownNow();
-    scheduledServiced.shutdown();
-    try {
-      scheduledServiced.awaitTermination(1, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      LOGGER.error(e);
-    }
-    scheduledServiced.shutdownNow();
-  }
-
-  public void gossipPerNodeData(PerNodeDataMessage message){
-    Objects.nonNull(message.getKey());
-    Objects.nonNull(message.getTimestamp());
-    Objects.nonNull(message.getPayload());
-    message.setNodeId(me.getId());
-    gossipCore.addPerNodeData(message);
-  }
-
-  public void gossipSharedData(SharedDataMessage message){
-    Objects.nonNull(message.getKey());
-    Objects.nonNull(message.getTimestamp());
-    Objects.nonNull(message.getPayload());
-    message.setNodeId(me.getId());
-    gossipCore.addSharedData(message);
-  }
-
-
-  @SuppressWarnings("rawtypes")
-  public Crdt findCrdt(String key){
-    SharedDataMessage l = gossipCore.getSharedData().get(key);
-    if (l == null){
-      return null;
-    }
-    if (l.getExpireAt() < clock.currentTimeMillis()){
-      return null;
-    } else {
-      return (Crdt) l.getPayload();
-    }
-  }
-
-  @SuppressWarnings("rawtypes")
-  public Crdt merge(SharedDataMessage message){
-    Objects.nonNull(message.getKey());
-    Objects.nonNull(message.getTimestamp());
-    Objects.nonNull(message.getPayload());
-    message.setNodeId(me.getId());
-    if (! (message.getPayload() instanceof Crdt)){
-      throw new IllegalArgumentException("Not a subclass of CRDT " + message.getPayload());
-    }
-    return gossipCore.merge(message);
-  }
-
-  public PerNodeDataMessage findPerNodeGossipData(String nodeId, String key){
-    ConcurrentHashMap<String, PerNodeDataMessage> j = gossipCore.getPerNodeData().get(nodeId);
-    if (j == null){
-      return null;
-    } else {
-      PerNodeDataMessage l = j.get(key);
-      if (l == null){
-        return null;
-      }
-      if (l.getExpireAt() != null && l.getExpireAt() < clock.currentTimeMillis()) {
-        return null;
-      }
-      return l;
-    }
-  }
-
-  public SharedDataMessage findSharedGossipData(String key){
-    SharedDataMessage l = gossipCore.getSharedData().get(key);
-    if (l == null){
-      return null;
-    }
-    if (l.getExpireAt() < clock.currentTimeMillis()){
-      return null;
-    } else {
-      return l;
-    }
-  }
-
-  public DataReaper getDataReaper() {
-    return dataReaper;
-  }
-
-  public RingStatePersister getRingState() {
-    return ringState;
-  }
-
-  public UserDataPersister getUserDataState() {
-    return userDataState;
-  }
-
-  public GossipMemberStateRefresher getMemberStateRefresher() {
-    return memberStateRefresher;
-  }
-
-  public Clock getClock() {
-    return clock;
-  }
-
-  public ObjectMapper getObjectMapper() {
-    return objectMapper;
-  }
-
-  public MetricRegistry getRegistry() {
-    return registry;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java b/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java
deleted file mode 100644
index b87045b..0000000
--- a/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java
+++ /dev/null
@@ -1,152 +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.manager;
-
-import com.codahale.metrics.MetricRegistry;
-import com.fasterxml.jackson.core.JsonGenerator.Feature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.gossip.Member;
-import org.apache.gossip.GossipSettings;
-import org.apache.gossip.StartupSettings;
-import org.apache.gossip.crdt.CrdtModule;
-import org.apache.gossip.event.GossipListener;
-import org.apache.gossip.manager.handlers.DefaultMessageInvoker;
-import org.apache.gossip.manager.handlers.MessageInvoker;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class GossipManagerBuilder {
-
-  public static ManagerBuilder newBuilder() {
-    return new ManagerBuilder();
-  }
-
-  public static final class ManagerBuilder {
-    private String cluster;
-    private URI uri;
-    private String id;
-    private GossipSettings settings;
-    private List<Member> gossipMembers;
-    private GossipListener listener;
-    private MetricRegistry registry;
-    private Map<String,String> properties;
-    private ObjectMapper objectMapper;
-    private MessageInvoker messageInvoker;
-
-    private ManagerBuilder() {}
-
-    private void checkArgument(boolean check, String msg) {
-      if (!check) {
-        throw new IllegalArgumentException(msg);
-      }
-    }
-
-    public ManagerBuilder cluster(String cluster) {
-      this.cluster = cluster;
-      return this;
-    }
-    
-    public ManagerBuilder properties(Map<String,String> properties) {
-      this.properties = properties;
-      return this;
-    }
-
-    public ManagerBuilder id(String id) {
-      this.id = id;
-      return this;
-    }
-
-    public ManagerBuilder gossipSettings(GossipSettings settings) {
-      this.settings = settings;
-      return this;
-    }
-    
-    public ManagerBuilder startupSettings(StartupSettings startupSettings) {
-      this.cluster = startupSettings.getCluster();
-      this.id = startupSettings.getId();
-      this.settings = startupSettings.getGossipSettings();
-      this.gossipMembers = startupSettings.getGossipMembers();
-      this.uri = startupSettings.getUri();
-      return this;
-    }
-
-    public ManagerBuilder gossipMembers(List<Member> members) {
-      this.gossipMembers = members;
-      return this;
-    }
-
-    public ManagerBuilder listener(GossipListener listener) {
-      this.listener = listener;
-      return this;
-    }
-    
-    public ManagerBuilder registry(MetricRegistry registry) {
-      this.registry = registry;
-      return this;
-    }
-
-    public ManagerBuilder uri(URI uri){
-      this.uri = uri;
-      return this;
-    }
-    
-    public ManagerBuilder mapper(ObjectMapper objectMapper){
-      this.objectMapper = objectMapper;
-      return this;
-    }
-
-    public ManagerBuilder messageInvoker(MessageInvoker messageInvoker) {
-      this.messageInvoker = messageInvoker;
-      return this;
-    }
-
-    public GossipManager build() {
-      checkArgument(id != null, "You must specify an id");
-      checkArgument(cluster != null, "You must specify a cluster name");
-      checkArgument(settings != null, "You must specify gossip settings");
-      checkArgument(uri != null, "You must specify a uri");
-      if (registry == null){
-        registry = new MetricRegistry();
-      }
-      if (properties == null){
-        properties = new HashMap<String,String>();
-      }
-      if (listener == null){
-        listener((a,b) -> {});
-      }
-      if (gossipMembers == null) {
-        gossipMembers = new ArrayList<>();
-      }
-      if (objectMapper == null) {
-        objectMapper = new ObjectMapper();
-        objectMapper.enableDefaultTyping();
-        objectMapper.registerModule(new CrdtModule());
-        objectMapper.configure(Feature.WRITE_NUMBERS_AS_STRINGS, false);
-      }
-      if (messageInvoker == null) {
-        messageInvoker = new DefaultMessageInvoker();
-      } 
-      return new GossipManager(cluster, uri, id, properties, settings, gossipMembers, listener, registry, objectMapper, messageInvoker) {} ;
-    }
-  }
-
-}


[2/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project

Posted by ec...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.java b/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.java
deleted file mode 100644
index 1836309..0000000
--- a/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.java
+++ /dev/null
@@ -1,121 +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.manager;
-
-import org.apache.gossip.GossipSettings;
-import org.apache.gossip.LocalMember;
-import org.apache.gossip.event.GossipListener;
-import org.apache.gossip.event.GossipState;
-import org.apache.gossip.model.PerNodeDataMessage;
-import org.apache.gossip.model.ShutdownMessage;
-import org.apache.log4j.Logger;
-
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiFunction;
-
-public class GossipMemberStateRefresher implements Runnable {
-  public static final Logger LOGGER = Logger.getLogger(GossipMemberStateRefresher.class);
-
-  private final Map<LocalMember, GossipState> members;
-  private final GossipSettings settings;
-  private final GossipListener listener;
-  private final Clock clock;
-  private final BiFunction<String, String, PerNodeDataMessage> findPerNodeGossipData;
-
-  public GossipMemberStateRefresher(Map<LocalMember, GossipState> members, GossipSettings settings,
-                                    GossipListener listener, BiFunction<String, String, PerNodeDataMessage> findPerNodeGossipData) {
-    this.members = members;
-    this.settings = settings;
-    this.listener = listener;
-    this.findPerNodeGossipData = findPerNodeGossipData;
-    clock = new SystemClock();
-  }
-
-  public void run() {
-    try {
-      runOnce();
-    } catch (RuntimeException ex) {
-      LOGGER.warn("scheduled state had exception", ex);
-    }
-  }
-
-  public void runOnce() {
-    for (Entry<LocalMember, GossipState> entry : members.entrySet()) {
-      boolean userDown = processOptimisticShutdown(entry);
-      if (userDown)
-        continue;
-
-      Double phiMeasure = entry.getKey().detect(clock.nanoTime());
-      GossipState requiredState;
-
-      if (phiMeasure != null) {
-        requiredState = calcRequiredState(phiMeasure);
-      } else {
-        requiredState = calcRequiredStateCleanupInterval(entry.getKey(), entry.getValue());
-      }
-
-      if (entry.getValue() != requiredState) {
-        members.put(entry.getKey(), requiredState);
-        listener.gossipEvent(entry.getKey(), requiredState);
-      }
-    }
-  }
-
-  public GossipState calcRequiredState(Double phiMeasure) {
-    if (phiMeasure > settings.getConvictThreshold())
-      return GossipState.DOWN;
-    else
-      return GossipState.UP;
-  }
-
-  public GossipState calcRequiredStateCleanupInterval(LocalMember member, GossipState state) {
-    long now = clock.nanoTime();
-    long nowInMillis = TimeUnit.MILLISECONDS.convert(now, TimeUnit.NANOSECONDS);
-    if (nowInMillis - settings.getCleanupInterval() > member.getHeartbeat()) {
-      return GossipState.DOWN;
-    } else {
-      return state;
-    }
-  }
-
-  /**
-   * If we have a special key the per-node data that means that the node has sent us
-   * a pre-emptive shutdown message. We process this so node is seen down sooner
-   *
-   * @param l member to consider
-   * @return true if node forced down
-   */
-  public boolean processOptimisticShutdown(Entry<LocalMember, GossipState> l) {
-    PerNodeDataMessage m = findPerNodeGossipData.apply(l.getKey().getId(), ShutdownMessage.PER_NODE_KEY);
-    if (m == null) {
-      return false;
-    }
-    ShutdownMessage s = (ShutdownMessage) m.getPayload();
-    if (s.getShutdownAtNanos() > l.getKey().getHeartbeat()) {
-      members.put(l.getKey(), GossipState.DOWN);
-      if (l.getValue() == GossipState.UP) {
-        listener.gossipEvent(l.getKey(), GossipState.DOWN);
-      }
-      return true;
-    }
-    return false;
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java b/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java
deleted file mode 100644
index 3bcc344..0000000
--- a/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java
+++ /dev/null
@@ -1,23 +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.manager;
-
-public interface PassiveGossipConstants {
-  String SIGNED_MESSAGE = "gossip.passive.signed_message";
-  String UNSIGNED_MESSAGE = "gossip.passive.unsigned_message";
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/PassiveGossipThread.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/PassiveGossipThread.java b/src/main/java/org/apache/gossip/manager/PassiveGossipThread.java
deleted file mode 100644
index ae28bf7..0000000
--- a/src/main/java/org/apache/gossip/manager/PassiveGossipThread.java
+++ /dev/null
@@ -1,114 +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.manager;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.gossip.model.Base;
-import org.apache.gossip.model.SignedPayload;
-import org.apache.log4j.Logger;
-
-import com.codahale.metrics.Meter;
-
-/**
- * This class handles the passive cycle,
- * where this client has received an incoming message. 
- */
-abstract public class PassiveGossipThread implements Runnable {
-
-  public static final Logger LOGGER = Logger.getLogger(PassiveGossipThread.class);
-
-  /** The socket used for the passive thread of the gossip service. */
-  private final DatagramSocket server;
-  private final AtomicBoolean keepRunning;
-  private final GossipCore gossipCore;
-  private final GossipManager gossipManager;
-  private final Meter signed;
-  private final Meter unsigned;
-
-  public PassiveGossipThread(GossipManager gossipManager, GossipCore gossipCore) {
-    this.gossipManager = gossipManager;
-    this.gossipCore = gossipCore;
-    if (gossipManager.getMyself().getClusterName() == null){
-      throw new IllegalArgumentException("Cluster was null");
-    }
-    try {
-      SocketAddress socketAddress = new InetSocketAddress(gossipManager.getMyself().getUri().getHost(),
-              gossipManager.getMyself().getUri().getPort());
-      server = new DatagramSocket(socketAddress);
-    } catch (SocketException ex) {
-      LOGGER.warn(ex);
-      throw new RuntimeException(ex);
-    }
-    keepRunning = new AtomicBoolean(true);
-    signed = gossipManager.getRegistry().meter(PassiveGossipConstants.SIGNED_MESSAGE);
-    unsigned = gossipManager.getRegistry().meter(PassiveGossipConstants.UNSIGNED_MESSAGE);
-  }
-
-  @Override
-  public void run() {
-    while (keepRunning.get()) {
-      try {
-        byte[] buf = new byte[server.getReceiveBufferSize()];
-        DatagramPacket p = new DatagramPacket(buf, buf.length);
-        server.receive(p);
-        debug(p.getData());
-        try {
-          Base activeGossipMessage = gossipManager.getObjectMapper().readValue(p.getData(), Base.class);
-          if (activeGossipMessage instanceof SignedPayload){
-            SignedPayload s = (SignedPayload) activeGossipMessage;
-            Base nested = gossipManager.getObjectMapper().readValue(s.getData(), Base.class);
-            gossipCore.receive(nested);
-            signed.mark();
-          } else {
-            gossipCore.receive(activeGossipMessage);
-            unsigned.mark();
-          }
-          gossipManager.getMemberStateRefresher().run();
-        } catch (RuntimeException ex) {//TODO trap json exception
-          LOGGER.error("Unable to process message", ex);
-        }
-      } catch (IOException e) {
-        LOGGER.error(e);
-        keepRunning.set(false);
-      }
-    }
-    shutdown();
-  }
-
-  private void debug(byte[] jsonBytes) {
-    if (LOGGER.isDebugEnabled()){
-      String receivedMessage = new String(jsonBytes);
-      LOGGER.debug("Received message ( bytes): " + receivedMessage);
-    }
-  }
-
-  public void shutdown() {
-    try {
-      server.close();
-    } catch (RuntimeException ex) {
-    }
-  }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/RingStatePersister.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/RingStatePersister.java b/src/main/java/org/apache/gossip/manager/RingStatePersister.java
deleted file mode 100644
index 7e42562..0000000
--- a/src/main/java/org/apache/gossip/manager/RingStatePersister.java
+++ /dev/null
@@ -1,76 +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.manager;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.NavigableSet;
-
-import org.apache.gossip.LocalMember;
-import org.apache.log4j.Logger;
-
-public class RingStatePersister implements Runnable {
-
-  private static final Logger LOGGER = Logger.getLogger(RingStatePersister.class);
-  private GossipManager parent;
-  
-  public RingStatePersister(GossipManager parent){
-    this.parent = parent;
-  }
-  
-  @Override
-  public void run() {
-    writeToDisk();
-  }
-  
-  File computeTarget(){
-    return new File(parent.getSettings().getPathToRingState(), "ringstate." + parent.getMyself().getClusterName() + "." 
-            + parent.getMyself().getId() + ".json");
-  }
-  
-  void writeToDisk(){
-    if (!parent.getSettings().isPersistRingState()){
-      return;
-    }
-    NavigableSet<LocalMember> i = parent.getMembers().keySet();
-    try (FileOutputStream fos = new FileOutputStream(computeTarget())){
-      parent.getObjectMapper().writeValue(fos, i);
-    } catch (IOException e) {
-      LOGGER.debug(e);
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  List<LocalMember> readFromDisk(){
-    if (!parent.getSettings().isPersistRingState()){
-      return Collections.emptyList();
-    }
-    try (FileInputStream fos = new FileInputStream(computeTarget())){
-      return parent.getObjectMapper().readValue(fos, ArrayList.class);
-    } catch (IOException e) {
-      LOGGER.debug(e);
-    }
-    return Collections.emptyList();
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java b/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java
deleted file mode 100644
index e47fe2a..0000000
--- a/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java
+++ /dev/null
@@ -1,110 +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.manager;
-
-import java.util.List;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.gossip.LocalMember;
-
-import com.codahale.metrics.MetricRegistry;
-
-/**
- * Base implementation gossips randomly to live nodes periodically gossips to dead ones
- *
- */
-public class SimpleActiveGossipper extends AbstractActiveGossiper {
-
-  private ScheduledExecutorService scheduledExecutorService;
-  private final BlockingQueue<Runnable> workQueue;
-  private ThreadPoolExecutor threadService;
-  
-  public SimpleActiveGossipper(GossipManager gossipManager, GossipCore gossipCore,
-          MetricRegistry registry) {
-    super(gossipManager, gossipCore, registry);
-    scheduledExecutorService = Executors.newScheduledThreadPool(2);
-    workQueue = new ArrayBlockingQueue<Runnable>(1024);
-    threadService = new ThreadPoolExecutor(1, 30, 1, TimeUnit.SECONDS, workQueue,
-            new ThreadPoolExecutor.DiscardOldestPolicy());
-  }
-
-  @Override
-  public void init() {
-    super.init();
-    scheduledExecutorService.scheduleAtFixedRate(() -> {
-      threadService.execute(() -> {
-        sendToALiveMember();
-      });
-    }, 0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
-    scheduledExecutorService.scheduleAtFixedRate(() -> {
-      sendToDeadMember();
-    }, 0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
-    scheduledExecutorService.scheduleAtFixedRate(
-            () -> sendPerNodeData(gossipManager.getMyself(),
-                    selectPartner(gossipManager.getLiveMembers())),
-            0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
-    scheduledExecutorService.scheduleAtFixedRate(
-            () -> sendSharedData(gossipManager.getMyself(),
-                    selectPartner(gossipManager.getLiveMembers())),
-            0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
-  }
-  
-  @Override
-  public void shutdown() {
-    super.shutdown();
-    scheduledExecutorService.shutdown();
-    try {
-      scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      LOGGER.debug("Issue during shutdown", e);
-    }
-    sendShutdownMessage();
-    threadService.shutdown();
-    try {
-      threadService.awaitTermination(5, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      LOGGER.debug("Issue during shutdown", e);
-    }
-  }
-
-  protected void sendToALiveMember(){
-    LocalMember member = selectPartner(gossipManager.getLiveMembers());
-    sendMembershipList(gossipManager.getMyself(), member);
-  }
-  
-  protected void sendToDeadMember(){
-    LocalMember member = selectPartner(gossipManager.getDeadMembers());
-    sendMembershipList(gossipManager.getMyself(), member);
-  }
-  
-  /**
-   * sends an optimistic shutdown message to several clusters nodes
-   */
-  protected void sendShutdownMessage(){
-    List<LocalMember> l = gossipManager.getLiveMembers();
-    int sendTo = l.size() < 3 ? 1 : l.size() / 2;
-    for (int i = 0; i < sendTo; i++) {
-      threadService.execute(() -> sendShutdownMessage(gossipManager.getMyself(), selectPartner(l)));
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/SystemClock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/SystemClock.java b/src/main/java/org/apache/gossip/manager/SystemClock.java
deleted file mode 100644
index 04a7080..0000000
--- a/src/main/java/org/apache/gossip/manager/SystemClock.java
+++ /dev/null
@@ -1,32 +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.manager;
-
-public class SystemClock implements Clock {
-
-  @Override
-  public long currentTimeMillis() {
-    return System.currentTimeMillis();
-  }
-
-  @Override
-  public long nanoTime() {
-    return System.nanoTime();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/UserDataPersister.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/UserDataPersister.java b/src/main/java/org/apache/gossip/manager/UserDataPersister.java
deleted file mode 100644
index 3b9eafa..0000000
--- a/src/main/java/org/apache/gossip/manager/UserDataPersister.java
+++ /dev/null
@@ -1,107 +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.manager;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.gossip.model.PerNodeDataMessage;
-import org.apache.gossip.model.SharedDataMessage;
-import org.apache.log4j.Logger;
-
-public class UserDataPersister implements Runnable {
-  
-  private static final Logger LOGGER = Logger.getLogger(UserDataPersister.class);
-  private final GossipManager parent;
-  private final GossipCore gossipCore; 
-  
-  UserDataPersister(GossipManager parent, GossipCore gossipCore){
-    this.parent = parent;
-    this.gossipCore = gossipCore;
-  }
-  
-  File computeSharedTarget(){
-    return new File(parent.getSettings().getPathToDataState(), "shareddata."
-            + parent.getMyself().getClusterName() + "." + parent.getMyself().getId() + ".json");
-  }
-  
-  File computePerNodeTarget() {
-    return new File(parent.getSettings().getPathToDataState(), "pernodedata."
-            + parent.getMyself().getClusterName() + "." + parent.getMyself().getId() + ".json");
-  }
-  
-  @SuppressWarnings("unchecked")
-  ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> readPerNodeFromDisk(){
-    if (!parent.getSettings().isPersistDataState()){
-      return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
-    }
-    try (FileInputStream fos = new FileInputStream(computePerNodeTarget())){
-      return parent.getObjectMapper().readValue(fos, ConcurrentHashMap.class);
-    } catch (IOException e) {
-      LOGGER.debug(e);
-    }
-    return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
-  }
-  
-  void writePerNodeToDisk(){
-    if (!parent.getSettings().isPersistDataState()){
-      return;
-    }
-    try (FileOutputStream fos = new FileOutputStream(computePerNodeTarget())){
-      parent.getObjectMapper().writeValue(fos, gossipCore.getPerNodeData());
-    } catch (IOException e) {
-      LOGGER.warn(e);
-    }
-  }
-  
-  void writeSharedToDisk(){
-    if (!parent.getSettings().isPersistDataState()){
-      return;
-    }
-    try (FileOutputStream fos = new FileOutputStream(computeSharedTarget())){
-      parent.getObjectMapper().writeValue(fos, gossipCore.getSharedData());
-    } catch (IOException e) {
-      LOGGER.warn(e);
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  ConcurrentHashMap<String, SharedDataMessage> readSharedDataFromDisk(){
-    if (!parent.getSettings().isPersistRingState()){
-      return new ConcurrentHashMap<String, SharedDataMessage>();
-    }
-    try (FileInputStream fos = new FileInputStream(computeSharedTarget())){
-      return parent.getObjectMapper().readValue(fos, ConcurrentHashMap.class);
-    } catch (IOException e) {
-      LOGGER.debug(e);
-    }
-    return new ConcurrentHashMap<String, SharedDataMessage>();
-  }
-  
-  /**
-   * Writes all pernode and shared data to disk 
-   */
-  @Override
-  public void run() {
-    writePerNodeToDisk();
-    writeSharedToDisk();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java b/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java
deleted file mode 100644
index f5e568e..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java
+++ /dev/null
@@ -1,74 +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.manager.handlers;
-
-import org.apache.gossip.Member;
-import org.apache.gossip.RemoteMember;
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-import org.apache.gossip.udp.UdpActiveGossipMessage;
-import org.apache.gossip.udp.UdpActiveGossipOk;
-import org.apache.gossip.udp.UdpNotAMemberFault;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ActiveGossipMessageHandler implements MessageHandler {
-  @Override
-  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    List<Member> remoteGossipMembers = new ArrayList<>();
-    RemoteMember senderMember = null;
-    UdpActiveGossipMessage activeGossipMessage = (UdpActiveGossipMessage) base;
-    for (int i = 0; i < activeGossipMessage.getMembers().size(); i++) {
-      URI u;
-      try {
-        u = new URI(activeGossipMessage.getMembers().get(i).getUri());
-      } catch (URISyntaxException e) {
-        GossipCore.LOGGER.debug("Gossip message with faulty URI", e);
-        continue;
-      }
-      RemoteMember member = new RemoteMember(
-              activeGossipMessage.getMembers().get(i).getCluster(),
-              u,
-              activeGossipMessage.getMembers().get(i).getId(),
-              activeGossipMessage.getMembers().get(i).getHeartbeat(),
-              activeGossipMessage.getMembers().get(i).getProperties());
-      if (i == 0) {
-        senderMember = member;
-      }
-      if (!(member.getClusterName().equals(gossipManager.getMyself().getClusterName()))) {
-        UdpNotAMemberFault f = new UdpNotAMemberFault();
-        f.setException("Not a member of this cluster " + i);
-        f.setUriFrom(activeGossipMessage.getUriFrom());
-        f.setUuid(activeGossipMessage.getUuid());
-        GossipCore.LOGGER.warn(f);
-        gossipCore.sendOneWay(f, member.getUri());
-        continue;
-      }
-      remoteGossipMembers.add(member);
-    }
-    UdpActiveGossipOk o = new UdpActiveGossipOk();
-    o.setUriFrom(activeGossipMessage.getUriFrom());
-    o.setUuid(activeGossipMessage.getUuid());
-    gossipCore.sendOneWay(o, senderMember.getUri());
-    gossipCore.mergeLists(gossipManager, senderMember, remoteGossipMembers);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java b/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java
deleted file mode 100644
index 5b78ce3..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java
+++ /dev/null
@@ -1,40 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.*;
-
-public class DefaultMessageInvoker implements MessageInvoker {
-  private final MessageInvokerCombiner mic;
-
-  public DefaultMessageInvoker() {
-    mic = new MessageInvokerCombiner();
-    mic.add(new SimpleMessageInvoker(Response.class, new ResponseHandler()));
-    mic.add(new SimpleMessageInvoker(ShutdownMessage.class, new ShutdownMessageHandler()));
-    mic.add(new SimpleMessageInvoker(PerNodeDataMessage.class, new PerNodeDataMessageHandler()));
-    mic.add(new SimpleMessageInvoker(SharedDataMessage.class, new SharedDataMessageHandler()));
-    mic.add(new SimpleMessageInvoker(ActiveGossipMessage.class, new ActiveGossipMessageHandler()));
-  }
-
-  public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    return mic.invoke(gossipCore, gossipManager, base);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.java b/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.java
deleted file mode 100644
index 4b5d49d..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-
-public interface MessageHandler {
-  void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base);
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java b/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java
deleted file mode 100644
index 70be408..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java
+++ /dev/null
@@ -1,33 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-
-public interface MessageInvoker {
-  /**
-   * 
-   * @param gossipCore
-   * @param gossipManager
-   * @param base
-   * @return true if the invoker processed the message type
-   */
-  boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base);
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java b/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java
deleted file mode 100644
index 5faf6a5..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java
+++ /dev/null
@@ -1,48 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-public class MessageInvokerCombiner implements MessageInvoker {
-  private final List<MessageInvoker> invokers = new CopyOnWriteArrayList<>();
-
-  public MessageInvokerCombiner() {
-  }
-
-  public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    return invokers.stream().filter((mi) -> mi.invoke(gossipCore, gossipManager, base)).count() > 0;
-  }
-
-  public void clear() {
-    invokers.clear();
-  }
-
-  public void add(MessageInvoker mi) {
-    if (mi == null) {
-      throw new NullPointerException();
-    }
-    invokers.add(mi);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java b/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java
deleted file mode 100644
index b3a785e..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java
+++ /dev/null
@@ -1,31 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-import org.apache.gossip.udp.UdpPerNodeDataMessage;
-
-public class PerNodeDataMessageHandler implements MessageHandler {
-  @Override
-  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    UdpPerNodeDataMessage message = (UdpPerNodeDataMessage) base;
-    gossipCore.addPerNodeData(message);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java b/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java
deleted file mode 100644
index 2f33b01..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java
+++ /dev/null
@@ -1,33 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-import org.apache.gossip.udp.Trackable;
-
-public class ResponseHandler implements MessageHandler {
-  @Override
-  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    if (base instanceof Trackable) {
-      Trackable t = (Trackable) base;
-      gossipCore.handleResponse(t.getUuid() + "/" + t.getUriFrom(), (Base) t);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java b/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java
deleted file mode 100644
index 89ca4a0..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java
+++ /dev/null
@@ -1,31 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-import org.apache.gossip.udp.UdpSharedDataMessage;
-
-public class SharedDataMessageHandler implements MessageHandler{
-  @Override
-  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    UdpSharedDataMessage message = (UdpSharedDataMessage) base;
-    gossipCore.addSharedData(message);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.java b/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.java
deleted file mode 100644
index a40c7a1..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.java
+++ /dev/null
@@ -1,38 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-import org.apache.gossip.model.PerNodeDataMessage;
-import org.apache.gossip.model.ShutdownMessage;
-
-public class ShutdownMessageHandler implements MessageHandler {
-  @Override
-  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    ShutdownMessage s = (ShutdownMessage) base;
-    PerNodeDataMessage m = new PerNodeDataMessage();
-    m.setKey(ShutdownMessage.PER_NODE_KEY);
-    m.setNodeId(s.getNodeId());
-    m.setPayload(base);
-    m.setTimestamp(System.currentTimeMillis());
-    m.setExpireAt(System.currentTimeMillis() + 30L * 1000L);
-    gossipCore.addPerNodeData(m);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java b/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java
deleted file mode 100644
index 0f410d2..0000000
--- a/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java
+++ /dev/null
@@ -1,45 +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.manager.handlers;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.model.Base;
-
-public class SimpleMessageInvoker implements MessageInvoker {
-  final private Class<?> messageClass;
-  final private MessageHandler messageHandler;
-
-  public SimpleMessageInvoker(Class<?> messageClass, MessageHandler messageHandler) {
-    if (messageClass == null || messageHandler == null) {
-      throw new NullPointerException();
-    }
-    this.messageClass = messageClass;
-    this.messageHandler = messageHandler;
-  }
-
-  @Override
-  public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
-    if (messageClass.isAssignableFrom(base.getClass())) {
-      messageHandler.invoke(gossipCore, gossipManager, base);
-      return true;
-    } else {
-      return false;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java b/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java
deleted file mode 100644
index dff5056..0000000
--- a/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java
+++ /dev/null
@@ -1,33 +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.manager.impl;
-
-import org.apache.gossip.manager.GossipCore;
-import org.apache.gossip.manager.GossipManager;
-import org.apache.gossip.manager.PassiveGossipThread;
-import org.apache.log4j.Logger;
-
-public class OnlyProcessReceivedPassiveGossipThread extends PassiveGossipThread {
-  
-  public static final Logger LOGGER = Logger.getLogger(OnlyProcessReceivedPassiveGossipThread.class);
-
-  public OnlyProcessReceivedPassiveGossipThread(GossipManager gossipManager, GossipCore gossipCore) {
-    super(gossipManager, gossipCore);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/ActiveGossipMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/ActiveGossipMessage.java b/src/main/java/org/apache/gossip/model/ActiveGossipMessage.java
deleted file mode 100644
index a3c45b8..0000000
--- a/src/main/java/org/apache/gossip/model/ActiveGossipMessage.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.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ActiveGossipMessage extends Base {
-
-  private List<Member> members = new ArrayList<>();
-  
-  public ActiveGossipMessage(){
-    
-  }
-
-  public List<Member> getMembers() {
-    return members;
-  }
-
-  public void setMembers(List<Member> members) {
-    this.members = members;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/ActiveGossipOk.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/ActiveGossipOk.java b/src/main/java/org/apache/gossip/model/ActiveGossipOk.java
deleted file mode 100644
index b54bf9a..0000000
--- a/src/main/java/org/apache/gossip/model/ActiveGossipOk.java
+++ /dev/null
@@ -1,22 +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.model;
-
-public class ActiveGossipOk extends Response {
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/Base.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/Base.java b/src/main/java/org/apache/gossip/model/Base.java
deleted file mode 100644
index 1b66310..0000000
--- a/src/main/java/org/apache/gossip/model/Base.java
+++ /dev/null
@@ -1,49 +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.model;
-
-import org.apache.gossip.udp.UdpActiveGossipMessage;
-import org.apache.gossip.udp.UdpActiveGossipOk;
-import org.apache.gossip.udp.UdpPerNodeDataMessage;
-import org.apache.gossip.udp.UdpNotAMemberFault;
-import org.apache.gossip.udp.UdpSharedDataMessage;
-
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
-
-
-@JsonTypeInfo(  
-        use = JsonTypeInfo.Id.CLASS,  
-        include = JsonTypeInfo.As.PROPERTY,  
-        property = "type") 
-@JsonSubTypes({
-        @Type(value = ActiveGossipMessage.class, name = "ActiveGossipMessage"),
-        @Type(value = Fault.class, name = "Fault"),
-        @Type(value = ActiveGossipOk.class, name = "ActiveGossipOk"),
-        @Type(value = UdpActiveGossipOk.class, name = "UdpActiveGossipOk"),
-        @Type(value = UdpActiveGossipMessage.class, name = "UdpActiveGossipMessage"),
-        @Type(value = UdpNotAMemberFault.class, name = "UdpNotAMemberFault"),
-        @Type(value = PerNodeDataMessage.class, name = "PerNodeDataMessage"),
-        @Type(value = UdpPerNodeDataMessage.class, name = "UdpPerNodeDataMessage"),
-        @Type(value = SharedDataMessage.class, name = "SharedDataMessage"),
-        @Type(value = UdpSharedDataMessage.class, name = "UdpSharedDataMessage")
-        })
-public class Base {
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/Fault.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/Fault.java b/src/main/java/org/apache/gossip/model/Fault.java
deleted file mode 100644
index 3ba2508..0000000
--- a/src/main/java/org/apache/gossip/model/Fault.java
+++ /dev/null
@@ -1,40 +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.model;
-
-public abstract class Fault extends Response {
-
-  private String exception;
-
-  public Fault(){}
-
-  public String getException() {
-    return exception;
-  }
-
-  public void setException(String exception) {
-    this.exception = exception;
-  }
-
-  @Override
-  public String toString() {
-    return "Fault [exception=" + exception + "]";
-  }
-
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/Member.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/Member.java b/src/main/java/org/apache/gossip/model/Member.java
deleted file mode 100644
index d86aad8..0000000
--- a/src/main/java/org/apache/gossip/model/Member.java
+++ /dev/null
@@ -1,87 +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.model;
-
-import java.util.Map;
-
-public class Member {
-
-  private String cluster;
-  private String uri;
-  private String id;
-  private Long heartbeat;
-  private Map<String,String> properties;
-  
-  public Member(){
-    
-  }
-  
-  public Member(String cluster, String uri, String id, Long heartbeat){
-    this.cluster = cluster;
-    this.uri = uri;
-    this.id = id;
-    this.heartbeat = heartbeat;
-  }
-
-  public String getCluster() {
-    return cluster;
-  }
-
-  public void setCluster(String cluster) {
-    this.cluster = cluster;
-  }
-
-  public String getUri() {
-    return uri;
-  }
-
-  public void setUri(String uri) {
-    this.uri = uri;
-  }
-
-  public String getId() {
-    return id;
-  }
-
-  public void setId(String id) {
-    this.id = id;
-  }
-
-  public Long getHeartbeat() {
-    return heartbeat;
-  }
-
-  public void setHeartbeat(Long heartbeat) {
-    this.heartbeat = heartbeat;
-  }
-
-  public Map<String, String> getProperties() {
-    return properties;
-  }
-
-  public void setProperties(Map<String, String> properties) {
-    this.properties = properties;
-  }
-
-  @Override
-  public String toString() {
-    return "Member [cluster=" + cluster + ", uri=" + uri + ", id=" + id + ", heartbeat="
-            + heartbeat + ", properties=" + properties + "]";
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/Message.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/Message.java b/src/main/java/org/apache/gossip/model/Message.java
deleted file mode 100644
index f6ed813..0000000
--- a/src/main/java/org/apache/gossip/model/Message.java
+++ /dev/null
@@ -1,22 +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.model;
-
-public class Message extends Base {
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/NotAMemberFault.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/NotAMemberFault.java b/src/main/java/org/apache/gossip/model/NotAMemberFault.java
deleted file mode 100644
index 21ffb07..0000000
--- a/src/main/java/org/apache/gossip/model/NotAMemberFault.java
+++ /dev/null
@@ -1,29 +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.model;
-
-public class NotAMemberFault extends Fault {
-
-  public NotAMemberFault(){
-    
-  }
-  
-  public NotAMemberFault(String message){
-    this.setException(message);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java b/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java
deleted file mode 100644
index 2d1cdef..0000000
--- a/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java
+++ /dev/null
@@ -1,66 +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.model;
-
-public class PerNodeDataMessage extends Base {
-
-  private String nodeId;
-  private String key;
-  private Object payload;
-  private Long timestamp;
-  private Long expireAt;
-  
-  public String getNodeId() {
-    return nodeId;
-  }
-  public void setNodeId(String nodeId) {
-    this.nodeId = nodeId;
-  }
-  public String getKey() {
-    return key;
-  }
-  public void setKey(String key) {
-    this.key = key;
-  }
-  public Object getPayload() {
-    return payload;
-  }
-  public void setPayload(Object payload) {
-    this.payload = payload;
-  }
-  public Long getTimestamp() {
-    return timestamp;
-  }
-  public void setTimestamp(Long timestamp) {
-    this.timestamp = timestamp;
-  }
-  public Long getExpireAt() {
-    return expireAt;
-  }
-  public void setExpireAt(Long expireAt) {
-    this.expireAt = expireAt;
-  }
-  @Override
-  public String toString() {
-    return "GossipDataMessage [nodeId=" + nodeId + ", key=" + key + ", payload=" + payload
-            + ", timestamp=" + timestamp + ", expireAt=" + expireAt + "]";
-  }
-
-  
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/Response.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/Response.java b/src/main/java/org/apache/gossip/model/Response.java
deleted file mode 100644
index b3eef77..0000000
--- a/src/main/java/org/apache/gossip/model/Response.java
+++ /dev/null
@@ -1,22 +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.model;
-
-public abstract class Response extends Base {
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/SharedDataMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/SharedDataMessage.java b/src/main/java/org/apache/gossip/model/SharedDataMessage.java
deleted file mode 100644
index e423be8..0000000
--- a/src/main/java/org/apache/gossip/model/SharedDataMessage.java
+++ /dev/null
@@ -1,64 +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.model;
-
-public class SharedDataMessage extends Base {
-
-  private String nodeId;
-  private String key;
-  private Object payload;
-  private Long timestamp;
-  private Long expireAt;
-  
-  public String getNodeId() {
-    return nodeId;
-  }
-  public void setNodeId(String nodeId) {
-    this.nodeId = nodeId;
-  }
-  public String getKey() {
-    return key;
-  }
-  public void setKey(String key) {
-    this.key = key;
-  }
-  public Object getPayload() {
-    return payload;
-  }
-  public void setPayload(Object payload) {
-    this.payload = payload;
-  }
-  public Long getTimestamp() {
-    return timestamp;
-  }
-  public void setTimestamp(Long timestamp) {
-    this.timestamp = timestamp;
-  }
-  public Long getExpireAt() {
-    return expireAt;
-  }
-  public void setExpireAt(Long expireAt) {
-    this.expireAt = expireAt;
-  }
-  @Override
-  public String toString() {
-    return "SharedGossipDataMessage [nodeId=" + nodeId + ", key=" + key + ", payload=" + payload
-            + ", timestamp=" + timestamp + ", expireAt=" + expireAt + "]";
-  }  
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/ShutdownMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/ShutdownMessage.java b/src/main/java/org/apache/gossip/model/ShutdownMessage.java
deleted file mode 100644
index 4bca508..0000000
--- a/src/main/java/org/apache/gossip/model/ShutdownMessage.java
+++ /dev/null
@@ -1,51 +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.model;
-
-public class ShutdownMessage extends Message {
-
-  public static final String PER_NODE_KEY = "gossipcore.shutdowmessage";
-  private long shutdownAtNanos;
-  private String nodeId;
-  
-  public ShutdownMessage(){
-    
-  }
-
-  public String getNodeId() {
-    return nodeId;
-  }
-
-  public void setNodeId(String nodeId) {
-    this.nodeId = nodeId;
-  }
-
-  public long getShutdownAtNanos() {
-    return shutdownAtNanos;
-  }
-
-  public void setShutdownAtNanos(long shutdownAtNanos) {
-    this.shutdownAtNanos = shutdownAtNanos;
-  }
-
-  @Override
-  public String toString() {
-    return "ShutdownMessage [shutdownAtNanos=" + shutdownAtNanos + ", nodeId=" + nodeId + "]";
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/model/SignedPayload.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/model/SignedPayload.java b/src/main/java/org/apache/gossip/model/SignedPayload.java
deleted file mode 100644
index 9ffbcf1..0000000
--- a/src/main/java/org/apache/gossip/model/SignedPayload.java
+++ /dev/null
@@ -1,36 +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.model;
-
-public class SignedPayload extends Base{
-  private byte [] data;
-  private byte [] signature;
-  public byte[] getData() {
-    return data;
-  }
-  public void setData(byte[] data) {
-    this.data = data;
-  }
-  public byte[] getSignature() {
-    return signature;
-  }
-  public void setSignature(byte[] signature) {
-    this.signature = signature;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/secure/KeyTool.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/secure/KeyTool.java b/src/main/java/org/apache/gossip/secure/KeyTool.java
deleted file mode 100644
index 69f4e72..0000000
--- a/src/main/java/org/apache/gossip/secure/KeyTool.java
+++ /dev/null
@@ -1,57 +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.secure;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-
-public class KeyTool {
-
-  public static void generatePubandPrivateKeyFiles(String path, String id) 
-          throws NoSuchAlgorithmException, NoSuchProviderException, IOException{
-    SecureRandom r = new SecureRandom();
-    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
-    keyGen.initialize(1024, r);
-    KeyPair pair = keyGen.generateKeyPair();
-    PrivateKey priv = pair.getPrivate();
-    PublicKey pub = pair.getPublic();
-    {
-      FileOutputStream sigfos = new FileOutputStream(new File(path, id));
-      sigfos.write(priv.getEncoded());
-      sigfos.close();
-    }
-    {
-      FileOutputStream sigfos = new FileOutputStream(new File(path, id + ".pub"));
-      sigfos.write(pub.getEncoded());
-      sigfos.close();
-    }
-  }
-  
-  public static void main (String [] args) throws 
-    NoSuchAlgorithmException, NoSuchProviderException, IOException{
-    generatePubandPrivateKeyFiles(args[0], args[1]);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/udp/Trackable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/udp/Trackable.java b/src/main/java/org/apache/gossip/udp/Trackable.java
deleted file mode 100644
index 9ecc7f2..0000000
--- a/src/main/java/org/apache/gossip/udp/Trackable.java
+++ /dev/null
@@ -1,30 +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.udp;
-
-public interface Trackable {
-
-  String getUriFrom();
-  
-  void setUriFrom(String uriFrom);
-  
-  String getUuid();
-  
-  void setUuid(String uuid);
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java b/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java
deleted file mode 100644
index b6e8101..0000000
--- a/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java
+++ /dev/null
@@ -1,49 +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.udp;
-
-import org.apache.gossip.model.ActiveGossipMessage;
-
-public class UdpActiveGossipMessage extends ActiveGossipMessage implements Trackable {
-
-  private String uriFrom;
-  private String uuid;
-  
-  public String getUriFrom() {
-    return uriFrom;
-  }
-  
-  public void setUriFrom(String uriFrom) {
-    this.uriFrom = uriFrom;
-  }
-  
-  public String getUuid() {
-    return uuid;
-  }
-  
-  public void setUuid(String uuid) {
-    this.uuid = uuid;
-  }
-
-  @Override
-  public String toString() {
-    return "UdpActiveGossipMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + ", getMembers()="
-            + getMembers() + "]";
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java b/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java
deleted file mode 100644
index b70bb69..0000000
--- a/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java
+++ /dev/null
@@ -1,44 +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.udp;
-
-import org.apache.gossip.model.ActiveGossipOk;
-
-public class UdpActiveGossipOk extends ActiveGossipOk implements Trackable {
-
-
-  private String uriFrom;
-  private String uuid;
-  
-  public String getUriFrom() {
-    return uriFrom;
-  }
-  
-  public void setUriFrom(String uriFrom) {
-    this.uriFrom = uriFrom;
-  }
-  
-  public String getUuid() {
-    return uuid;
-  }
-  
-  public void setUuid(String uuid) {
-    this.uuid = uuid;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java b/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java
deleted file mode 100644
index 7afcb87..0000000
--- a/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java
+++ /dev/null
@@ -1,46 +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.udp;
-
-import org.apache.gossip.model.NotAMemberFault;
-
-public class UdpNotAMemberFault extends NotAMemberFault implements Trackable{
-
-  public UdpNotAMemberFault(){
-    
-  }
-  private String uriFrom;
-  private String uuid;
-  
-  public String getUriFrom() {
-    return uriFrom;
-  }
-  
-  public void setUriFrom(String uriFrom) {
-    this.uriFrom = uriFrom;
-  }
-  
-  public String getUuid() {
-    return uuid;
-  }
-  
-  public void setUuid(String uuid) {
-    this.uuid = uuid;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java b/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java
deleted file mode 100644
index 6eb170a..0000000
--- a/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java
+++ /dev/null
@@ -1,48 +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.udp;
-
-import org.apache.gossip.model.PerNodeDataMessage;
-
-public class UdpPerNodeDataMessage extends PerNodeDataMessage implements Trackable {
-
-  private String uriFrom;
-  private String uuid;
-  
-  public String getUriFrom() {
-    return uriFrom;
-  }
-  
-  public void setUriFrom(String uriFrom) {
-    this.uriFrom = uriFrom;
-  }
-  
-  public String getUuid() {
-    return uuid;
-  }
-  
-  public void setUuid(String uuid) {
-    this.uuid = uuid;
-  }
-
-  @Override
-  public String toString() {
-    return "UdpGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + "]";
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java b/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java
deleted file mode 100644
index 1658503..0000000
--- a/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java
+++ /dev/null
@@ -1,50 +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.udp;
-
-import org.apache.gossip.model.SharedDataMessage;
-
-public class UdpSharedDataMessage extends SharedDataMessage implements Trackable {
-
-  private String uriFrom;
-  private String uuid;
-  
-  public String getUriFrom() {
-    return uriFrom;
-  }
-  
-  public void setUriFrom(String uriFrom) {
-    this.uriFrom = uriFrom;
-  }
-  
-  public String getUuid() {
-    return uuid;
-  }
-  
-  public void setUuid(String uuid) {
-    this.uuid = uuid;
-  }
-
-  @Override
-  public String toString() {
-    return "UdpSharedGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + ", getNodeId()="
-            + getNodeId() + ", getKey()=" + getKey() + ", getPayload()=" + getPayload()
-            + ", getTimestamp()=" + getTimestamp() + ", getExpireAt()=" + getExpireAt() + "]";
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
deleted file mode 100644
index e2a60e1..0000000
--- a/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#  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/src/test/java/org/apache/gossip/AbstractIntegrationBase.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/gossip/AbstractIntegrationBase.java b/src/test/java/org/apache/gossip/AbstractIntegrationBase.java
deleted file mode 100644
index 896157f..0000000
--- a/src/test/java/org/apache/gossip/AbstractIntegrationBase.java
+++ /dev/null
@@ -1,50 +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.ArrayList;
-import java.util.List;
-
-import org.apache.gossip.manager.GossipManager;
-import org.junit.After;
-import org.junit.Before;
-
-public abstract class AbstractIntegrationBase {
-
-  List <GossipManager> nodes = new ArrayList<GossipManager>();
-  
-  public void register(GossipManager manager){
-    nodes.add(manager);
-  }
-    
-  @Before
-  public void before(){
-    nodes = new ArrayList<GossipManager>();
-  }
-  
-  @After
-  public void after(){
-    for (GossipManager node: nodes){
-      if (node !=null){
-        node.shutdown();
-      }
-    }
-  }
-  
-}



[4/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project

Posted by ec...@apache.org.
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> {
-
-}
-



[5/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project

Posted by ec...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.java
new file mode 100644
index 0000000..4b5d49d
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageHandler.java
@@ -0,0 +1,26 @@
+/*
+ * 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.Base;
+
+public interface MessageHandler {
+  void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java
new file mode 100644
index 0000000..70be408
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvoker.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.gossip.manager.handlers;
+
+import org.apache.gossip.manager.GossipCore;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.model.Base;
+
+public interface MessageInvoker {
+  /**
+   * 
+   * @param gossipCore
+   * @param gossipManager
+   * @param base
+   * @return true if the invoker processed the message type
+   */
+  boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base);
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java
new file mode 100644
index 0000000..5faf6a5
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/MessageInvokerCombiner.java
@@ -0,0 +1,48 @@
+/*
+ * 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.Base;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class MessageInvokerCombiner implements MessageInvoker {
+  private final List<MessageInvoker> invokers = new CopyOnWriteArrayList<>();
+
+  public MessageInvokerCombiner() {
+  }
+
+  public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    return invokers.stream().filter((mi) -> mi.invoke(gossipCore, gossipManager, base)).count() > 0;
+  }
+
+  public void clear() {
+    invokers.clear();
+  }
+
+  public void add(MessageInvoker mi) {
+    if (mi == null) {
+      throw new NullPointerException();
+    }
+    invokers.add(mi);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java
new file mode 100644
index 0000000..b3a785e
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/PerNodeDataMessageHandler.java
@@ -0,0 +1,31 @@
+/*
+ * 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.Base;
+import org.apache.gossip.udp.UdpPerNodeDataMessage;
+
+public class PerNodeDataMessageHandler implements MessageHandler {
+  @Override
+  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    UdpPerNodeDataMessage message = (UdpPerNodeDataMessage) base;
+    gossipCore.addPerNodeData(message);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java
new file mode 100644
index 0000000..2f33b01
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ResponseHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.gossip.manager.handlers;
+
+import org.apache.gossip.manager.GossipCore;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.model.Base;
+import org.apache.gossip.udp.Trackable;
+
+public class ResponseHandler implements MessageHandler {
+  @Override
+  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    if (base instanceof Trackable) {
+      Trackable t = (Trackable) base;
+      gossipCore.handleResponse(t.getUuid() + "/" + t.getUriFrom(), (Base) t);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java
new file mode 100644
index 0000000..89ca4a0
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SharedDataMessageHandler.java
@@ -0,0 +1,31 @@
+/*
+ * 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.Base;
+import org.apache.gossip.udp.UdpSharedDataMessage;
+
+public class SharedDataMessageHandler implements MessageHandler{
+  @Override
+  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    UdpSharedDataMessage message = (UdpSharedDataMessage) base;
+    gossipCore.addSharedData(message);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.java
new file mode 100644
index 0000000..a40c7a1
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ShutdownMessageHandler.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.manager.handlers;
+
+import org.apache.gossip.manager.GossipCore;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.model.Base;
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.ShutdownMessage;
+
+public class ShutdownMessageHandler implements MessageHandler {
+  @Override
+  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    ShutdownMessage s = (ShutdownMessage) base;
+    PerNodeDataMessage m = new PerNodeDataMessage();
+    m.setKey(ShutdownMessage.PER_NODE_KEY);
+    m.setNodeId(s.getNodeId());
+    m.setPayload(base);
+    m.setTimestamp(System.currentTimeMillis());
+    m.setExpireAt(System.currentTimeMillis() + 30L * 1000L);
+    gossipCore.addPerNodeData(m);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java
new file mode 100644
index 0000000..0f410d2
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/SimpleMessageInvoker.java
@@ -0,0 +1,45 @@
+/*
+ * 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.Base;
+
+public class SimpleMessageInvoker implements MessageInvoker {
+  final private Class<?> messageClass;
+  final private MessageHandler messageHandler;
+
+  public SimpleMessageInvoker(Class<?> messageClass, MessageHandler messageHandler) {
+    if (messageClass == null || messageHandler == null) {
+      throw new NullPointerException();
+    }
+    this.messageClass = messageClass;
+    this.messageHandler = messageHandler;
+  }
+
+  @Override
+  public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    if (messageClass.isAssignableFrom(base.getClass())) {
+      messageHandler.invoke(gossipCore, gossipManager, base);
+      return true;
+    } else {
+      return false;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java b/gossip-base/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java
new file mode 100644
index 0000000..dff5056
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/impl/OnlyProcessReceivedPassiveGossipThread.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.gossip.manager.impl;
+
+import org.apache.gossip.manager.GossipCore;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.PassiveGossipThread;
+import org.apache.log4j.Logger;
+
+public class OnlyProcessReceivedPassiveGossipThread extends PassiveGossipThread {
+  
+  public static final Logger LOGGER = Logger.getLogger(OnlyProcessReceivedPassiveGossipThread.class);
+
+  public OnlyProcessReceivedPassiveGossipThread(GossipManager gossipManager, GossipCore gossipCore) {
+    super(gossipManager, gossipCore);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipMessage.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipMessage.java b/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipMessage.java
new file mode 100644
index 0000000..a3c45b8
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipMessage.java
@@ -0,0 +1,39 @@
+/*
+ * 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.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ActiveGossipMessage extends Base {
+
+  private List<Member> members = new ArrayList<>();
+  
+  public ActiveGossipMessage(){
+    
+  }
+
+  public List<Member> getMembers() {
+    return members;
+  }
+
+  public void setMembers(List<Member> members) {
+    this.members = members;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipOk.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipOk.java b/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipOk.java
new file mode 100644
index 0000000..b54bf9a
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/ActiveGossipOk.java
@@ -0,0 +1,22 @@
+/*
+ * 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.model;
+
+public class ActiveGossipOk extends Response {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/Base.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/Base.java b/gossip-base/src/main/java/org/apache/gossip/model/Base.java
new file mode 100644
index 0000000..1b66310
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/Base.java
@@ -0,0 +1,49 @@
+/*
+ * 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.model;
+
+import org.apache.gossip.udp.UdpActiveGossipMessage;
+import org.apache.gossip.udp.UdpActiveGossipOk;
+import org.apache.gossip.udp.UdpPerNodeDataMessage;
+import org.apache.gossip.udp.UdpNotAMemberFault;
+import org.apache.gossip.udp.UdpSharedDataMessage;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+
+
+@JsonTypeInfo(  
+        use = JsonTypeInfo.Id.CLASS,  
+        include = JsonTypeInfo.As.PROPERTY,  
+        property = "type") 
+@JsonSubTypes({
+        @Type(value = ActiveGossipMessage.class, name = "ActiveGossipMessage"),
+        @Type(value = Fault.class, name = "Fault"),
+        @Type(value = ActiveGossipOk.class, name = "ActiveGossipOk"),
+        @Type(value = UdpActiveGossipOk.class, name = "UdpActiveGossipOk"),
+        @Type(value = UdpActiveGossipMessage.class, name = "UdpActiveGossipMessage"),
+        @Type(value = UdpNotAMemberFault.class, name = "UdpNotAMemberFault"),
+        @Type(value = PerNodeDataMessage.class, name = "PerNodeDataMessage"),
+        @Type(value = UdpPerNodeDataMessage.class, name = "UdpPerNodeDataMessage"),
+        @Type(value = SharedDataMessage.class, name = "SharedDataMessage"),
+        @Type(value = UdpSharedDataMessage.class, name = "UdpSharedDataMessage")
+        })
+public class Base {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/Fault.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/Fault.java b/gossip-base/src/main/java/org/apache/gossip/model/Fault.java
new file mode 100644
index 0000000..3ba2508
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/Fault.java
@@ -0,0 +1,40 @@
+/*
+ * 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.model;
+
+public abstract class Fault extends Response {
+
+  private String exception;
+
+  public Fault(){}
+
+  public String getException() {
+    return exception;
+  }
+
+  public void setException(String exception) {
+    this.exception = exception;
+  }
+
+  @Override
+  public String toString() {
+    return "Fault [exception=" + exception + "]";
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/Member.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/Member.java b/gossip-base/src/main/java/org/apache/gossip/model/Member.java
new file mode 100644
index 0000000..d86aad8
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/Member.java
@@ -0,0 +1,87 @@
+/*
+ * 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.model;
+
+import java.util.Map;
+
+public class Member {
+
+  private String cluster;
+  private String uri;
+  private String id;
+  private Long heartbeat;
+  private Map<String,String> properties;
+  
+  public Member(){
+    
+  }
+  
+  public Member(String cluster, String uri, String id, Long heartbeat){
+    this.cluster = cluster;
+    this.uri = uri;
+    this.id = id;
+    this.heartbeat = heartbeat;
+  }
+
+  public String getCluster() {
+    return cluster;
+  }
+
+  public void setCluster(String cluster) {
+    this.cluster = cluster;
+  }
+
+  public String getUri() {
+    return uri;
+  }
+
+  public void setUri(String uri) {
+    this.uri = uri;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public Long getHeartbeat() {
+    return heartbeat;
+  }
+
+  public void setHeartbeat(Long heartbeat) {
+    this.heartbeat = heartbeat;
+  }
+
+  public Map<String, String> getProperties() {
+    return properties;
+  }
+
+  public void setProperties(Map<String, String> properties) {
+    this.properties = properties;
+  }
+
+  @Override
+  public String toString() {
+    return "Member [cluster=" + cluster + ", uri=" + uri + ", id=" + id + ", heartbeat="
+            + heartbeat + ", properties=" + properties + "]";
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/Message.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/Message.java b/gossip-base/src/main/java/org/apache/gossip/model/Message.java
new file mode 100644
index 0000000..f6ed813
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/Message.java
@@ -0,0 +1,22 @@
+/*
+ * 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.model;
+
+public class Message extends Base {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/NotAMemberFault.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/NotAMemberFault.java b/gossip-base/src/main/java/org/apache/gossip/model/NotAMemberFault.java
new file mode 100644
index 0000000..21ffb07
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/NotAMemberFault.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model;
+
+public class NotAMemberFault extends Fault {
+
+  public NotAMemberFault(){
+    
+  }
+  
+  public NotAMemberFault(String message){
+    this.setException(message);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java b/gossip-base/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java
new file mode 100644
index 0000000..2d1cdef
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/PerNodeDataMessage.java
@@ -0,0 +1,66 @@
+/*
+ * 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.model;
+
+public class PerNodeDataMessage extends Base {
+
+  private String nodeId;
+  private String key;
+  private Object payload;
+  private Long timestamp;
+  private Long expireAt;
+  
+  public String getNodeId() {
+    return nodeId;
+  }
+  public void setNodeId(String nodeId) {
+    this.nodeId = nodeId;
+  }
+  public String getKey() {
+    return key;
+  }
+  public void setKey(String key) {
+    this.key = key;
+  }
+  public Object getPayload() {
+    return payload;
+  }
+  public void setPayload(Object payload) {
+    this.payload = payload;
+  }
+  public Long getTimestamp() {
+    return timestamp;
+  }
+  public void setTimestamp(Long timestamp) {
+    this.timestamp = timestamp;
+  }
+  public Long getExpireAt() {
+    return expireAt;
+  }
+  public void setExpireAt(Long expireAt) {
+    this.expireAt = expireAt;
+  }
+  @Override
+  public String toString() {
+    return "GossipDataMessage [nodeId=" + nodeId + ", key=" + key + ", payload=" + payload
+            + ", timestamp=" + timestamp + ", expireAt=" + expireAt + "]";
+  }
+
+  
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/Response.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/Response.java b/gossip-base/src/main/java/org/apache/gossip/model/Response.java
new file mode 100644
index 0000000..b3eef77
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/Response.java
@@ -0,0 +1,22 @@
+/*
+ * 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.model;
+
+public abstract class Response extends Base {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/SharedDataMessage.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/SharedDataMessage.java b/gossip-base/src/main/java/org/apache/gossip/model/SharedDataMessage.java
new file mode 100644
index 0000000..e423be8
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/SharedDataMessage.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.model;
+
+public class SharedDataMessage extends Base {
+
+  private String nodeId;
+  private String key;
+  private Object payload;
+  private Long timestamp;
+  private Long expireAt;
+  
+  public String getNodeId() {
+    return nodeId;
+  }
+  public void setNodeId(String nodeId) {
+    this.nodeId = nodeId;
+  }
+  public String getKey() {
+    return key;
+  }
+  public void setKey(String key) {
+    this.key = key;
+  }
+  public Object getPayload() {
+    return payload;
+  }
+  public void setPayload(Object payload) {
+    this.payload = payload;
+  }
+  public Long getTimestamp() {
+    return timestamp;
+  }
+  public void setTimestamp(Long timestamp) {
+    this.timestamp = timestamp;
+  }
+  public Long getExpireAt() {
+    return expireAt;
+  }
+  public void setExpireAt(Long expireAt) {
+    this.expireAt = expireAt;
+  }
+  @Override
+  public String toString() {
+    return "SharedGossipDataMessage [nodeId=" + nodeId + ", key=" + key + ", payload=" + payload
+            + ", timestamp=" + timestamp + ", expireAt=" + expireAt + "]";
+  }  
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/ShutdownMessage.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/ShutdownMessage.java b/gossip-base/src/main/java/org/apache/gossip/model/ShutdownMessage.java
new file mode 100644
index 0000000..4bca508
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/ShutdownMessage.java
@@ -0,0 +1,51 @@
+/*
+ * 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.model;
+
+public class ShutdownMessage extends Message {
+
+  public static final String PER_NODE_KEY = "gossipcore.shutdowmessage";
+  private long shutdownAtNanos;
+  private String nodeId;
+  
+  public ShutdownMessage(){
+    
+  }
+
+  public String getNodeId() {
+    return nodeId;
+  }
+
+  public void setNodeId(String nodeId) {
+    this.nodeId = nodeId;
+  }
+
+  public long getShutdownAtNanos() {
+    return shutdownAtNanos;
+  }
+
+  public void setShutdownAtNanos(long shutdownAtNanos) {
+    this.shutdownAtNanos = shutdownAtNanos;
+  }
+
+  @Override
+  public String toString() {
+    return "ShutdownMessage [shutdownAtNanos=" + shutdownAtNanos + ", nodeId=" + nodeId + "]";
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/model/SignedPayload.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/model/SignedPayload.java b/gossip-base/src/main/java/org/apache/gossip/model/SignedPayload.java
new file mode 100644
index 0000000..9ffbcf1
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/model/SignedPayload.java
@@ -0,0 +1,36 @@
+/*
+ * 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.model;
+
+public class SignedPayload extends Base{
+  private byte [] data;
+  private byte [] signature;
+  public byte[] getData() {
+    return data;
+  }
+  public void setData(byte[] data) {
+    this.data = data;
+  }
+  public byte[] getSignature() {
+    return signature;
+  }
+  public void setSignature(byte[] signature) {
+    this.signature = signature;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/secure/KeyTool.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/secure/KeyTool.java b/gossip-base/src/main/java/org/apache/gossip/secure/KeyTool.java
new file mode 100644
index 0000000..69f4e72
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/secure/KeyTool.java
@@ -0,0 +1,57 @@
+/*
+ * 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.secure;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+
+public class KeyTool {
+
+  public static void generatePubandPrivateKeyFiles(String path, String id) 
+          throws NoSuchAlgorithmException, NoSuchProviderException, IOException{
+    SecureRandom r = new SecureRandom();
+    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
+    keyGen.initialize(1024, r);
+    KeyPair pair = keyGen.generateKeyPair();
+    PrivateKey priv = pair.getPrivate();
+    PublicKey pub = pair.getPublic();
+    {
+      FileOutputStream sigfos = new FileOutputStream(new File(path, id));
+      sigfos.write(priv.getEncoded());
+      sigfos.close();
+    }
+    {
+      FileOutputStream sigfos = new FileOutputStream(new File(path, id + ".pub"));
+      sigfos.write(pub.getEncoded());
+      sigfos.close();
+    }
+  }
+  
+  public static void main (String [] args) throws 
+    NoSuchAlgorithmException, NoSuchProviderException, IOException{
+    generatePubandPrivateKeyFiles(args[0], args[1]);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/udp/Trackable.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/udp/Trackable.java b/gossip-base/src/main/java/org/apache/gossip/udp/Trackable.java
new file mode 100644
index 0000000..9ecc7f2
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/udp/Trackable.java
@@ -0,0 +1,30 @@
+/*
+ * 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.udp;
+
+public interface Trackable {
+
+  String getUriFrom();
+  
+  void setUriFrom(String uriFrom);
+  
+  String getUuid();
+  
+  void setUuid(String uuid);
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java b/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java
new file mode 100644
index 0000000..b6e8101
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipMessage.java
@@ -0,0 +1,49 @@
+/*
+ * 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.udp;
+
+import org.apache.gossip.model.ActiveGossipMessage;
+
+public class UdpActiveGossipMessage extends ActiveGossipMessage implements Trackable {
+
+  private String uriFrom;
+  private String uuid;
+  
+  public String getUriFrom() {
+    return uriFrom;
+  }
+  
+  public void setUriFrom(String uriFrom) {
+    this.uriFrom = uriFrom;
+  }
+  
+  public String getUuid() {
+    return uuid;
+  }
+  
+  public void setUuid(String uuid) {
+    this.uuid = uuid;
+  }
+
+  @Override
+  public String toString() {
+    return "UdpActiveGossipMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + ", getMembers()="
+            + getMembers() + "]";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java b/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java
new file mode 100644
index 0000000..b70bb69
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/udp/UdpActiveGossipOk.java
@@ -0,0 +1,44 @@
+/*
+ * 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.udp;
+
+import org.apache.gossip.model.ActiveGossipOk;
+
+public class UdpActiveGossipOk extends ActiveGossipOk implements Trackable {
+
+
+  private String uriFrom;
+  private String uuid;
+  
+  public String getUriFrom() {
+    return uriFrom;
+  }
+  
+  public void setUriFrom(String uriFrom) {
+    this.uriFrom = uriFrom;
+  }
+  
+  public String getUuid() {
+    return uuid;
+  }
+  
+  public void setUuid(String uuid) {
+    this.uuid = uuid;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java b/gossip-base/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java
new file mode 100644
index 0000000..7afcb87
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/udp/UdpNotAMemberFault.java
@@ -0,0 +1,46 @@
+/*
+ * 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.udp;
+
+import org.apache.gossip.model.NotAMemberFault;
+
+public class UdpNotAMemberFault extends NotAMemberFault implements Trackable{
+
+  public UdpNotAMemberFault(){
+    
+  }
+  private String uriFrom;
+  private String uuid;
+  
+  public String getUriFrom() {
+    return uriFrom;
+  }
+  
+  public void setUriFrom(String uriFrom) {
+    this.uriFrom = uriFrom;
+  }
+  
+  public String getUuid() {
+    return uuid;
+  }
+  
+  public void setUuid(String uuid) {
+    this.uuid = uuid;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java b/gossip-base/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java
new file mode 100644
index 0000000..6eb170a
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/udp/UdpPerNodeDataMessage.java
@@ -0,0 +1,48 @@
+/*
+ * 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.udp;
+
+import org.apache.gossip.model.PerNodeDataMessage;
+
+public class UdpPerNodeDataMessage extends PerNodeDataMessage implements Trackable {
+
+  private String uriFrom;
+  private String uuid;
+  
+  public String getUriFrom() {
+    return uriFrom;
+  }
+  
+  public void setUriFrom(String uriFrom) {
+    this.uriFrom = uriFrom;
+  }
+  
+  public String getUuid() {
+    return uuid;
+  }
+  
+  public void setUuid(String uuid) {
+    this.uuid = uuid;
+  }
+
+  @Override
+  public String toString() {
+    return "UdpGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + "]";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java b/gossip-base/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java
new file mode 100644
index 0000000..1658503
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/udp/UdpSharedDataMessage.java
@@ -0,0 +1,50 @@
+/*
+ * 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.udp;
+
+import org.apache.gossip.model.SharedDataMessage;
+
+public class UdpSharedDataMessage extends SharedDataMessage implements Trackable {
+
+  private String uriFrom;
+  private String uuid;
+  
+  public String getUriFrom() {
+    return uriFrom;
+  }
+  
+  public void setUriFrom(String uriFrom) {
+    this.uriFrom = uriFrom;
+  }
+  
+  public String getUuid() {
+    return uuid;
+  }
+  
+  public void setUuid(String uuid) {
+    this.uuid = uuid;
+  }
+
+  @Override
+  public String toString() {
+    return "UdpSharedGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + ", getNodeId()="
+            + getNodeId() + ", getKey()=" + getKey() + ", getPayload()=" + getPayload()
+            + ", getTimestamp()=" + getTimestamp() + ", getExpireAt()=" + getExpireAt() + "]";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/resources/log4j.properties b/gossip-base/src/main/resources/log4j.properties
new file mode 100644
index 0000000..e2a60e1
--- /dev/null
+++ b/gossip-base/src/main/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/gossip-base/src/test/java/org/apache/gossip/AbstractIntegrationBase.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/AbstractIntegrationBase.java b/gossip-base/src/test/java/org/apache/gossip/AbstractIntegrationBase.java
new file mode 100644
index 0000000..896157f
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/AbstractIntegrationBase.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.gossip.manager.GossipManager;
+import org.junit.After;
+import org.junit.Before;
+
+public abstract class AbstractIntegrationBase {
+
+  List <GossipManager> nodes = new ArrayList<GossipManager>();
+  
+  public void register(GossipManager manager){
+    nodes.add(manager);
+  }
+    
+  @Before
+  public void before(){
+    nodes = new ArrayList<GossipManager>();
+  }
+  
+  @After
+  public void after(){
+    for (GossipManager node: nodes){
+      if (node !=null){
+        node.shutdown();
+      }
+    }
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/DataTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/DataTest.java b/gossip-base/src/test/java/org/apache/gossip/DataTest.java
new file mode 100644
index 0000000..f0c2186
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/DataTest.java
@@ -0,0 +1,238 @@
+/*
+ * 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.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.gossip.crdt.GrowOnlyCounter;
+import org.apache.gossip.crdt.GrowOnlySet;
+import org.apache.gossip.crdt.OrSet;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.SharedDataMessage;
+import org.junit.Test;
+
+import io.teknek.tunit.TUnit;
+
+public class DataTest extends AbstractIntegrationBase {
+  
+  private String orSetKey = "cror";
+  private String gCounterKey = "crdtgc";
+  
+  @Test
+  public void dataTest() throws InterruptedException, UnknownHostException, URISyntaxException{
+    GossipSettings settings = new GossipSettings();
+    settings.setPersistRingState(false);
+    settings.setPersistDataState(false);
+    String cluster = UUID.randomUUID().toString();
+    int seedNodes = 1;
+    List<Member> startupMembers = new ArrayList<>();
+    for (int i = 1; i < seedNodes+1; ++i) {
+      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
+      startupMembers.add(new RemoteMember(cluster, uri, i + ""));
+    }
+    final List<GossipManager> clients = new ArrayList<>();
+    final int clusterMembers = 2;
+    for (int i = 1; i < clusterMembers + 1; ++i) {
+      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
+      GossipManager gossipService = GossipManagerBuilder.newBuilder().cluster(cluster).uri(uri)
+              .id(i + "").gossipMembers(startupMembers).gossipSettings(settings).build();
+      clients.add(gossipService);
+      gossipService.init();
+      register(gossipService);
+    }
+    TUnit.assertThat(() -> {
+      int total = 0;
+      for (int i = 0; i < clusterMembers; ++i) {
+        total += clients.get(i).getLiveMembers().size();
+      }
+      return total;
+    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo(2);
+    clients.get(0).gossipPerNodeData(msg());
+    clients.get(0).gossipSharedData(sharedMsg());
+
+    TUnit.assertThat(()-> {
+      PerNodeDataMessage x = clients.get(1).findPerNodeGossipData(1 + "", "a");
+      if (x == null)
+        return "";
+      else
+        return x.getPayload();
+    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo("b");
+   
+    TUnit.assertThat(() ->  {
+      SharedDataMessage x = clients.get(1).findSharedGossipData("a");
+      if (x == null)
+        return "";
+      else
+        return x.getPayload();
+    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo("c");
+    
+    
+    givenDifferentDatumsInSet(clients);
+    assertThatListIsMerged(clients);
+    
+    givenOrs(clients);
+    assertThatOrSetIsMerged(clients);
+    dropIt(clients);
+    assertThatOrSetDelIsMerged(clients);
+
+    
+    // test g counter
+    givenDifferentIncrement(clients);
+    assertThatCountIsUpdated(clients, 3);
+    givenIncreaseOther(clients);
+    assertThatCountIsUpdated(clients, 7);
+
+    for (int i = 0; i < clusterMembers; ++i) {
+      clients.get(i).shutdown();
+    }
+  }
+  
+  private void givenDifferentIncrement(final List<GossipManager> clients) {
+    {
+      SharedDataMessage d = new SharedDataMessage();
+      d.setKey(gCounterKey);
+      d.setPayload(new GrowOnlyCounter(new GrowOnlyCounter.Builder(clients.get(0)).increment(1L)));
+      d.setExpireAt(Long.MAX_VALUE);
+      d.setTimestamp(System.currentTimeMillis());
+      clients.get(0).merge(d);
+    }
+    {
+      SharedDataMessage d = new SharedDataMessage();
+      d.setKey(gCounterKey);
+      d.setPayload(new GrowOnlyCounter(new GrowOnlyCounter.Builder(clients.get(1)).increment(2L)));
+      d.setExpireAt(Long.MAX_VALUE);
+      d.setTimestamp(System.currentTimeMillis());
+      clients.get(1).merge(d);
+    }
+  }
+
+  private void givenIncreaseOther(final List<GossipManager> clients) {
+    GrowOnlyCounter gc = (GrowOnlyCounter) clients.get(1).findCrdt(gCounterKey);
+    GrowOnlyCounter gc2 = new GrowOnlyCounter(gc,
+            new GrowOnlyCounter.Builder(clients.get(1)).increment(4L));
+
+    SharedDataMessage d = new SharedDataMessage();
+    d.setKey(gCounterKey);
+    d.setPayload(gc2);
+    d.setExpireAt(Long.MAX_VALUE);
+    d.setTimestamp(System.currentTimeMillis());
+    clients.get(1).merge(d);
+  }
+
+  private void givenOrs(List<GossipManager> clients) {
+    {
+      SharedDataMessage d = new SharedDataMessage();
+      d.setKey(orSetKey);
+      d.setPayload(new OrSet<String>("1", "2"));
+      d.setExpireAt(Long.MAX_VALUE);
+      d.setTimestamp(System.currentTimeMillis());
+      clients.get(0).merge(d);
+    }
+    {
+      SharedDataMessage d = new SharedDataMessage();
+      d.setKey(orSetKey);
+      d.setPayload(new OrSet<String>("3", "4"));
+      d.setExpireAt(Long.MAX_VALUE);
+      d.setTimestamp(System.currentTimeMillis());
+      clients.get(1).merge(d);
+    }
+  }
+  
+  private void dropIt(List<GossipManager> clients) {
+    @SuppressWarnings("unchecked")
+    OrSet<String> o = (OrSet<String>) clients.get(0).findCrdt(orSetKey);
+    OrSet<String> o2 = new OrSet<String>(o, new OrSet.Builder<String>().remove("3"));
+    SharedDataMessage d = new SharedDataMessage();
+    d.setKey(orSetKey);
+    d.setPayload(o2);
+    d.setExpireAt(Long.MAX_VALUE);
+    d.setTimestamp(System.currentTimeMillis());
+    clients.get(0).merge(d);
+  }
+  
+  private void assertThatOrSetIsMerged(final List<GossipManager> clients){
+    TUnit.assertThat(() ->  {
+      return clients.get(0).findCrdt(orSetKey).value();
+    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new OrSet<String>("1", "2", "3", "4").value());
+    TUnit.assertThat(() ->  {
+      return clients.get(1).findCrdt(orSetKey).value();
+    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new OrSet<String>("1", "2", "3", "4").value());
+  }
+  
+  private void assertThatOrSetDelIsMerged(final List<GossipManager> clients){
+    TUnit.assertThat(() ->  {
+      return clients.get(0).findCrdt(orSetKey);
+    }).afterWaitingAtMost(10, TimeUnit.SECONDS).equals(new OrSet<String>("1", "2", "4"));
+  }
+
+  private void givenDifferentDatumsInSet(final List<GossipManager> clients){
+    clients.get(0).merge(CrdtMessage("1"));
+    clients.get(1).merge(CrdtMessage("2"));
+  }
+  
+
+  private void assertThatCountIsUpdated(final List<GossipManager> clients, long finalCount) {
+    TUnit.assertThat(() -> {
+      return clients.get(0).findCrdt(gCounterKey);
+    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new GrowOnlyCounter(
+            new GrowOnlyCounter.Builder(clients.get(0)).increment(finalCount)));
+  }
+
+  private void assertThatListIsMerged(final List<GossipManager> clients){
+    TUnit.assertThat(() ->  {
+      return clients.get(0).findCrdt("cr");
+    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(new GrowOnlySet<String>(Arrays.asList("1","2")));
+  }
+  
+  private SharedDataMessage CrdtMessage(String item){
+    SharedDataMessage d = new SharedDataMessage();
+    d.setKey("cr");
+    d.setPayload(new GrowOnlySet<String>( Arrays.asList(item)));
+    d.setExpireAt(Long.MAX_VALUE);
+    d.setTimestamp(System.currentTimeMillis());
+    return d;
+  }
+  
+  private PerNodeDataMessage msg(){
+    PerNodeDataMessage g = new PerNodeDataMessage();
+    g.setExpireAt(Long.MAX_VALUE);
+    g.setKey("a");
+    g.setPayload("b");
+    g.setTimestamp(System.currentTimeMillis());
+    return g;
+  }
+  
+  private SharedDataMessage sharedMsg(){
+    SharedDataMessage g = new SharedDataMessage();
+    g.setExpireAt(Long.MAX_VALUE);
+    g.setKey("a");
+    g.setPayload("c");
+    g.setTimestamp(System.currentTimeMillis());
+    return g;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/IdAndPropertyTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/IdAndPropertyTest.java b/gossip-base/src/test/java/org/apache/gossip/IdAndPropertyTest.java
new file mode 100644
index 0000000..7f550de
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/IdAndPropertyTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit; 
+
+import org.apache.gossip.manager.DatacenterRackAwareActiveGossiper;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+import io.teknek.tunit.TUnit;
+
+@RunWith(JUnitPlatform.class)
+public class IdAndPropertyTest extends AbstractIntegrationBase {
+
+  @Test
+  public void testDatacenterRackGossiper() throws URISyntaxException, UnknownHostException, InterruptedException {
+    GossipSettings settings = new GossipSettings();
+    settings.setActiveGossipClass(DatacenterRackAwareActiveGossiper.class.getName());
+    List<Member> startupMembers = new ArrayList<>();
+    Map<String, String> x = new HashMap<>();
+    x.put("a", "b");
+    x.put("datacenter", "dc1");
+    x.put("rack", "rack1");
+    GossipManager gossipService1 = GossipManagerBuilder.newBuilder()
+            .cluster("a")
+            .uri(new URI("udp://" + "127.0.0.1" + ":" + (29000 + 0)))
+            .id("0")
+            .properties(x)
+            .gossipMembers(startupMembers)
+            .gossipSettings(settings).build();
+    gossipService1.init();
+    register(gossipService1);
+    
+    Map<String, String> y = new HashMap<>();
+    y.put("a", "c");
+    y.put("datacenter", "dc2");
+    y.put("rack", "rack2");
+    GossipManager gossipService2 = GossipManagerBuilder.newBuilder().cluster("a")
+            .uri( new URI("udp://" + "127.0.0.1" + ":" + (29000 + 10)))
+            .id("1")
+            .properties(y)
+            .gossipMembers(Arrays.asList(new RemoteMember("a",
+                    new URI("udp://" + "127.0.0.1" + ":" + (29000 + 0)), "0")))
+            .gossipSettings(settings).build();
+    gossipService2.init();
+    register(gossipService2);
+    
+    TUnit.assertThat(() -> { 
+      String value = ""; 
+      try {
+        value = gossipService1.getLiveMembers().get(0).getProperties().get("a");
+      } catch (RuntimeException e){ }
+      return value;
+    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo("c");
+    
+    TUnit.assertThat(() -> { 
+      String value = ""; 
+      try {
+        value = gossipService2.getLiveMembers().get(0).getProperties().get("a");
+      } catch (RuntimeException e){ }
+      return value;
+    }).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo("b");        
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/MemberTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/MemberTest.java b/gossip-base/src/test/java/org/apache/gossip/MemberTest.java
new file mode 100644
index 0000000..5f0d18a
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/MemberTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.net.URISyntaxException;
+import java.util.HashMap;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+@RunWith(JUnitPlatform.class)
+public class MemberTest {
+
+  @Test
+  public void testHashCodeFromGossip40() throws URISyntaxException {
+    Assert.assertNotEquals(
+            new LocalMember("mycluster", new URI("udp://4.4.4.4:1000"), "myid", 1, new HashMap<String,String>(), 10, 5, "exponential")
+                    .hashCode(),
+            new LocalMember("mycluster", new URI("udp://4.4.4.5:1005"), "yourid", 11, new HashMap<String,String>(), 11, 6, "exponential")
+                    .hashCode());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java b/gossip-base/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java
new file mode 100644
index 0000000..54005c3
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/ShutdownDeadtimeTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.apache.log4j.Logger;
+
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.jupiter.api.Test;
+
+import org.junit.runner.RunWith;
+
+@RunWith(JUnitPlatform.class)
+public class ShutdownDeadtimeTest {
+
+  private static final Logger log = Logger.getLogger(ShutdownDeadtimeTest.class);
+  
+  @Test
+  public void DeadNodesDoNotComeAliveAgain()
+          throws InterruptedException, UnknownHostException, URISyntaxException {
+    GossipSettings settings = new GossipSettings(100, 10000, 1000, 1, 10.0, "normal");
+    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" + ":" + (30300 + i));
+      startupMembers.add(new RemoteMember(cluster, uri, i + ""));
+    }
+    final List<GossipManager> clients = Collections.synchronizedList(new ArrayList<GossipManager>());
+    final int clusterMembers = 5;
+    for (int i = 1; i < clusterMembers + 1; ++i) {
+      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30300 + i));
+      GossipManager gossipService = GossipManagerBuilder.newBuilder()
+              .cluster(cluster)
+              .uri(uri)
+              .id(i + "")
+              .gossipMembers(startupMembers)
+              .gossipSettings(settings)
+              .build();
+      clients.add(gossipService);
+      gossipService.init();
+      
+    }
+    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);
+
+    // shutdown one client and verify that one client is lost.
+    Random r = new Random();
+    int randomClientId = r.nextInt(clusterMembers);
+    log.info("shutting down " + randomClientId);
+    final int shutdownPort = clients.get(randomClientId).getMyself().getUri()
+            .getPort();
+    final String shutdownId = clients.get(randomClientId).getMyself().getId();
+    clients.get(randomClientId).shutdown();
+    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(16);
+    clients.remove(randomClientId);
+
+    TUnit.assertThat(new Callable<Integer>() {
+      public Integer call() throws Exception {
+        int total = 0;
+        for (int i = 0; i < clusterMembers - 1; ++i) {
+          total += clients.get(i).getDeadMembers().size();
+        }
+        return total;
+      }
+    }).afterWaitingAtMost(50, TimeUnit.SECONDS).isEqualTo(4);
+
+    URI uri = new URI("udp://" + "127.0.0.1" + ":" + shutdownPort);
+    // start client again
+    GossipManager gossipService = GossipManagerBuilder.newBuilder()
+            .gossipSettings(settings)
+            .cluster(cluster)
+            .uri(uri)
+            .id(shutdownId+"")
+            .gossipMembers(startupMembers)
+            .build();
+    clients.add(gossipService);
+    gossipService.init();
+
+    // verify that the client is alive again for every node
+    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(60, TimeUnit.SECONDS).isEqualTo(20);
+
+    for (int i = 0; i < clusterMembers; ++i) {
+      final 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/SignedMessageTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/SignedMessageTest.java b/gossip-base/src/test/java/org/apache/gossip/SignedMessageTest.java
new file mode 100644
index 0000000..5c3bb76
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/SignedMessageTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.apache.gossip.manager.PassiveGossipConstants;
+import org.apache.gossip.secure.KeyTool;
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.teknek.tunit.TUnit;
+
+public class SignedMessageTest extends AbstractIntegrationBase {
+
+  @Test(expected = IllegalArgumentException.class)
+  public void ifSignMustHaveKeys()
+          throws URISyntaxException, UnknownHostException, InterruptedException {
+    String cluster = UUID.randomUUID().toString();
+    GossipSettings settings = gossiperThatSigns();
+    List<Member> startupMembers = new ArrayList<>();
+    URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30000 + 1));
+    GossipManager gossipService = GossipManagerBuilder.newBuilder()
+            .cluster(cluster)
+            .uri(uri)
+            .id(1 + "")
+            .gossipMembers(startupMembers)
+            .gossipSettings(settings)
+            .build();
+    gossipService.init();
+  }
+
+  private GossipSettings gossiperThatSigns(){
+    GossipSettings settings = new GossipSettings();
+    settings.setPersistRingState(false);
+    settings.setPersistDataState(false);
+    settings.setSignMessages(true);
+    return settings;
+  }
+  
+  private GossipSettings gossiperThatSigns(String keysDir){
+    GossipSettings settings = gossiperThatSigns();
+    settings.setPathToKeyStore(Objects.requireNonNull(keysDir));
+    return settings;
+  }
+  
+  @Test
+  public void dataTest() throws InterruptedException, URISyntaxException, NoSuchAlgorithmException, NoSuchProviderException, IOException {
+    final String keys = System.getProperty("java.io.tmpdir") + "/keys";
+    GossipSettings settings = gossiperThatSigns(keys);
+    setup(keys);
+    String cluster = UUID.randomUUID().toString();
+    List<Member> startupMembers = new ArrayList<>();
+    for (int i = 1; i < 2; ++i) {
+      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30000 + i));
+      startupMembers.add(new RemoteMember(cluster, uri, i + ""));
+    }
+    final List<GossipManager> clients = new ArrayList<>();
+    for (int i = 1; i < 3; ++i) {
+      URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30000 + i));
+      GossipManager gossipService = GossipManagerBuilder.newBuilder()
+              .cluster(cluster)
+              .uri(uri)
+              .id(i + "")
+              .gossipMembers(startupMembers)
+              .gossipSettings(settings)
+              .build();
+      gossipService.init();
+      clients.add(gossipService);
+    }
+    assertTwoAlive(clients);
+    assertOnlySignedMessages(clients);
+    cleanup(keys, clients);
+  }
+  
+  private void assertTwoAlive(List<GossipManager> clients){
+    TUnit.assertThat(() -> {
+      int total = 0;
+      for (int i = 0; i < clients.size(); ++i) {
+        total += clients.get(i).getLiveMembers().size();
+      }
+      return total;
+    }).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo(2);
+  }
+  
+  private void assertOnlySignedMessages(List<GossipManager> clients){
+    Assert.assertEquals(0, clients.get(0).getRegistry()
+            .meter(PassiveGossipConstants.UNSIGNED_MESSAGE).getCount());
+    Assert.assertTrue(clients.get(0).getRegistry()
+            .meter(PassiveGossipConstants.SIGNED_MESSAGE).getCount() > 0);
+  }
+  
+  private void cleanup(String keys, List<GossipManager> clients){
+    new File(keys, "1").delete();
+    new File(keys, "2").delete();
+    new File(keys).delete();
+    for (int i = 0; i < clients.size(); ++i) {
+      clients.get(i).shutdown();
+    }
+  }
+  
+  private void setup(String keys) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
+    new File(keys).mkdir();
+    KeyTool.generatePubandPrivateKeyFiles(keys, "1");
+    KeyTool.generatePubandPrivateKeyFiles(keys, "2");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/test/java/org/apache/gossip/StartupSettingsTest.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/test/java/org/apache/gossip/StartupSettingsTest.java b/gossip-base/src/test/java/org/apache/gossip/StartupSettingsTest.java
new file mode 100644
index 0000000..d6c4a1e
--- /dev/null
+++ b/gossip-base/src/test/java/org/apache/gossip/StartupSettingsTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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 org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.apache.log4j.Logger;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.UUID;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests support of using {@code StartupSettings} and thereby reading
+ * setup config from file.
+ */
+@RunWith(JUnitPlatform.class)
+public class StartupSettingsTest {
+  private static final Logger log = Logger.getLogger(StartupSettingsTest.class);
+  private static final String CLUSTER = UUID.randomUUID().toString();
+
+  @Test
+  public void testUsingSettingsFile() throws IOException, InterruptedException, URISyntaxException {
+    File settingsFile = File.createTempFile("gossipTest",".json");
+    settingsFile.deleteOnExit();
+    writeSettingsFile(settingsFile);
+    URI uri = new URI("udp://" + "127.0.0.1" + ":" + 50000);
+    GossipManager firstService = GossipManagerBuilder.newBuilder()
+            .cluster(CLUSTER)
+            .uri(uri)
+            .id("1")
+            .gossipSettings(new GossipSettings()).build();
+    firstService.init();
+    GossipManager manager = GossipManagerBuilder.newBuilder()
+            .startupSettings(StartupSettings.fromJSONFile(settingsFile)).build();
+    manager.init();
+    firstService.shutdown();
+    manager.shutdown();
+  }
+
+  private void writeSettingsFile( File target ) throws IOException {
+    String settings =
+            "[{\n" + // It is odd that this is meant to be in an array, but oh well.
+            "  \"cluster\":\"" + CLUSTER + "\",\n" +
+            "  \"id\":\"" + "2" + "\",\n" +
+            "  \"uri\":\"udp://127.0.0.1:50001\",\n" +
+            "  \"gossip_interval\":1000,\n" +
+            "  \"window_size\":1000,\n" +
+            "  \"minimum_samples\":5,\n" +
+            "  \"cleanup_interval\":10000,\n" +
+            "  \"convict_threshold\":2.6,\n" +
+            "  \"distribution\":\"exponential\",\n" +
+            "  \"properties\":{},\n" +
+            "  \"members\":[\n" +
+            "    {\"cluster\": \"" + CLUSTER + "\",\"uri\":\"udp://127.0.0.1:5000\"}\n" +
+            "  ]\n" +
+            "}]";
+
+    log.info( "Using settings file with contents of:\n---\n" + settings + "\n---" );
+    FileOutputStream output = new FileOutputStream(target);
+    output.write(settings.getBytes());
+    output.close();
+  }
+}



[7/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project

Posted by ec...@apache.org.
GOSSIP-78 refactor into a multi-module maven project

* add *.ipr to .gitignore
* modify existing pom to be a parent. create new pom for gossip-core.
* I left all properties and dependencies in the parent, as they seemed to be a fairly general set of dependencies.
move all the code.
* rename parent module: gossip -> gossip-parent
* move dependencies into child module


Project: http://git-wip-us.apache.org/repos/asf/incubator-gossip/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-gossip/commit/298b1ae3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-gossip/tree/298b1ae3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-gossip/diff/298b1ae3

Branch: refs/heads/master
Commit: 298b1ae3aeba575f39c6854e8f8039a6284cd470
Parents: 6a4d50c
Author: Gary Dusbabek <gd...@gmail.com>
Authored: Thu Apr 13 08:20:06 2017 -0500
Committer: Gary Dusbabek <gd...@gmail.com>
Committed: Thu Apr 13 10:12:23 2017 -0500

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 gossip-base/pom.xml                             |  91 +++++
 .../java/org/apache/gossip/GossipSettings.java  | 226 +++++++++++
 .../java/org/apache/gossip/LocalMember.java     |  71 ++++
 .../src/main/java/org/apache/gossip/Member.java | 166 ++++++++
 .../java/org/apache/gossip/RemoteMember.java    |  47 +++
 .../java/org/apache/gossip/StartupSettings.java | 207 ++++++++++
 .../apache/gossip/accrual/FailureDetector.java  |  80 ++++
 .../main/java/org/apache/gossip/crdt/Crdt.java  |  39 ++
 .../apache/gossip/crdt/CrdtBiFunctionMerge.java |  55 +++
 .../org/apache/gossip/crdt/CrdtCounter.java     |  24 ++
 .../java/org/apache/gossip/crdt/CrdtModule.java |  69 ++++
 .../java/org/apache/gossip/crdt/CrdtSet.java    |  26 ++
 .../org/apache/gossip/crdt/GrowOnlyCounter.java | 119 ++++++
 .../org/apache/gossip/crdt/GrowOnlySet.java     | 157 ++++++++
 .../main/java/org/apache/gossip/crdt/OrSet.java | 304 +++++++++++++++
 .../org/apache/gossip/event/GossipListener.java |  24 ++
 .../org/apache/gossip/event/GossipState.java    |  28 ++
 .../examples/StandAloneDatacenterAndRack.java   |  62 +++
 .../apache/gossip/examples/StandAloneNode.java  |  47 +++
 .../examples/StandAloneNodeCrdtOrSet.java       | 115 ++++++
 .../gossip/manager/AbstractActiveGossiper.java  | 171 ++++++++
 .../java/org/apache/gossip/manager/Clock.java   |  25 ++
 .../org/apache/gossip/manager/DataReaper.java   |  85 ++++
 .../DatacenterRackAwareActiveGossiper.java      | 244 ++++++++++++
 .../org/apache/gossip/manager/GossipCore.java   | 387 +++++++++++++++++++
 .../gossip/manager/GossipCoreConstants.java     |  30 ++
 .../apache/gossip/manager/GossipManager.java    | 319 +++++++++++++++
 .../gossip/manager/GossipManagerBuilder.java    | 152 ++++++++
 .../manager/GossipMemberStateRefresher.java     | 121 ++++++
 .../gossip/manager/PassiveGossipConstants.java  |  23 ++
 .../gossip/manager/PassiveGossipThread.java     | 114 ++++++
 .../gossip/manager/RingStatePersister.java      |  76 ++++
 .../gossip/manager/SimpleActiveGossipper.java   | 110 ++++++
 .../org/apache/gossip/manager/SystemClock.java  |  32 ++
 .../gossip/manager/UserDataPersister.java       | 107 +++++
 .../handlers/ActiveGossipMessageHandler.java    |  74 ++++
 .../manager/handlers/DefaultMessageInvoker.java |  40 ++
 .../gossip/manager/handlers/MessageHandler.java |  26 ++
 .../gossip/manager/handlers/MessageInvoker.java |  33 ++
 .../handlers/MessageInvokerCombiner.java        |  48 +++
 .../handlers/PerNodeDataMessageHandler.java     |  31 ++
 .../manager/handlers/ResponseHandler.java       |  33 ++
 .../handlers/SharedDataMessageHandler.java      |  31 ++
 .../handlers/ShutdownMessageHandler.java        |  38 ++
 .../manager/handlers/SimpleMessageInvoker.java  |  45 +++
 .../OnlyProcessReceivedPassiveGossipThread.java |  33 ++
 .../gossip/model/ActiveGossipMessage.java       |  39 ++
 .../org/apache/gossip/model/ActiveGossipOk.java |  22 ++
 .../main/java/org/apache/gossip/model/Base.java |  49 +++
 .../java/org/apache/gossip/model/Fault.java     |  40 ++
 .../java/org/apache/gossip/model/Member.java    |  87 +++++
 .../java/org/apache/gossip/model/Message.java   |  22 ++
 .../apache/gossip/model/NotAMemberFault.java    |  29 ++
 .../apache/gossip/model/PerNodeDataMessage.java |  66 ++++
 .../java/org/apache/gossip/model/Response.java  |  22 ++
 .../apache/gossip/model/SharedDataMessage.java  |  64 +++
 .../apache/gossip/model/ShutdownMessage.java    |  51 +++
 .../org/apache/gossip/model/SignedPayload.java  |  36 ++
 .../java/org/apache/gossip/secure/KeyTool.java  |  57 +++
 .../java/org/apache/gossip/udp/Trackable.java   |  30 ++
 .../gossip/udp/UdpActiveGossipMessage.java      |  49 +++
 .../apache/gossip/udp/UdpActiveGossipOk.java    |  44 +++
 .../apache/gossip/udp/UdpNotAMemberFault.java   |  46 +++
 .../gossip/udp/UdpPerNodeDataMessage.java       |  48 +++
 .../apache/gossip/udp/UdpSharedDataMessage.java |  50 +++
 gossip-base/src/main/resources/log4j.properties |  20 +
 .../apache/gossip/AbstractIntegrationBase.java  |  50 +++
 .../test/java/org/apache/gossip/DataTest.java   | 238 ++++++++++++
 .../org/apache/gossip/IdAndPropertyTest.java    |  91 +++++
 .../test/java/org/apache/gossip/MemberTest.java |  40 ++
 .../org/apache/gossip/ShutdownDeadtimeTest.java | 146 +++++++
 .../org/apache/gossip/SignedMessageTest.java    | 135 +++++++
 .../org/apache/gossip/StartupSettingsTest.java  |  86 +++++
 .../org/apache/gossip/TenNodeThreeSeedTest.java |  92 +++++
 .../gossip/accrual/FailureDetectorTest.java     | 113 ++++++
 .../apache/gossip/crdt/GrowOnlyCounterTest.java |  54 +++
 .../org/apache/gossip/crdt/GrowOnlySetTest.java |  38 ++
 .../java/org/apache/gossip/crdt/OrSetTest.java  | 115 ++++++
 .../apache/gossip/manager/DataReaperTest.java   | 104 +++++
 .../manager/GossipManagerBuilderTest.java       | 121 ++++++
 .../gossip/manager/RingPersistenceTest.java     |  64 +++
 .../gossip/manager/UserDataPersistenceTest.java | 114 ++++++
 .../manager/handlers/MessageInvokerTest.java    | 178 +++++++++
 gossip-base/src/test/resources/log4j.properties |  20 +
 pom.xml                                         | 207 ++++------
 .../java/org/apache/gossip/GossipSettings.java  | 226 -----------
 .../java/org/apache/gossip/LocalMember.java     |  71 ----
 src/main/java/org/apache/gossip/Member.java     | 166 --------
 .../java/org/apache/gossip/RemoteMember.java    |  47 ---
 .../java/org/apache/gossip/StartupSettings.java | 207 ----------
 .../apache/gossip/accrual/FailureDetector.java  |  80 ----
 src/main/java/org/apache/gossip/crdt/Crdt.java  |  39 --
 .../apache/gossip/crdt/CrdtBiFunctionMerge.java |  55 ---
 .../org/apache/gossip/crdt/CrdtCounter.java     |  24 --
 .../java/org/apache/gossip/crdt/CrdtModule.java |  69 ----
 .../java/org/apache/gossip/crdt/CrdtSet.java    |  26 --
 .../org/apache/gossip/crdt/GrowOnlyCounter.java | 119 ------
 .../org/apache/gossip/crdt/GrowOnlySet.java     | 157 --------
 src/main/java/org/apache/gossip/crdt/OrSet.java | 304 ---------------
 .../org/apache/gossip/event/GossipListener.java |  24 --
 .../org/apache/gossip/event/GossipState.java    |  28 --
 .../examples/StandAloneDatacenterAndRack.java   |  62 ---
 .../apache/gossip/examples/StandAloneNode.java  |  47 ---
 .../examples/StandAloneNodeCrdtOrSet.java       | 115 ------
 .../gossip/manager/AbstractActiveGossiper.java  | 171 --------
 .../java/org/apache/gossip/manager/Clock.java   |  25 --
 .../org/apache/gossip/manager/DataReaper.java   |  85 ----
 .../DatacenterRackAwareActiveGossiper.java      | 244 ------------
 .../org/apache/gossip/manager/GossipCore.java   | 387 -------------------
 .../gossip/manager/GossipCoreConstants.java     |  30 --
 .../apache/gossip/manager/GossipManager.java    | 319 ---------------
 .../gossip/manager/GossipManagerBuilder.java    | 152 --------
 .../manager/GossipMemberStateRefresher.java     | 121 ------
 .../gossip/manager/PassiveGossipConstants.java  |  23 --
 .../gossip/manager/PassiveGossipThread.java     | 114 ------
 .../gossip/manager/RingStatePersister.java      |  76 ----
 .../gossip/manager/SimpleActiveGossipper.java   | 110 ------
 .../org/apache/gossip/manager/SystemClock.java  |  32 --
 .../gossip/manager/UserDataPersister.java       | 107 -----
 .../handlers/ActiveGossipMessageHandler.java    |  74 ----
 .../manager/handlers/DefaultMessageInvoker.java |  40 --
 .../gossip/manager/handlers/MessageHandler.java |  26 --
 .../gossip/manager/handlers/MessageInvoker.java |  33 --
 .../handlers/MessageInvokerCombiner.java        |  48 ---
 .../handlers/PerNodeDataMessageHandler.java     |  31 --
 .../manager/handlers/ResponseHandler.java       |  33 --
 .../handlers/SharedDataMessageHandler.java      |  31 --
 .../handlers/ShutdownMessageHandler.java        |  38 --
 .../manager/handlers/SimpleMessageInvoker.java  |  45 ---
 .../OnlyProcessReceivedPassiveGossipThread.java |  33 --
 .../gossip/model/ActiveGossipMessage.java       |  39 --
 .../org/apache/gossip/model/ActiveGossipOk.java |  22 --
 src/main/java/org/apache/gossip/model/Base.java |  49 ---
 .../java/org/apache/gossip/model/Fault.java     |  40 --
 .../java/org/apache/gossip/model/Member.java    |  87 -----
 .../java/org/apache/gossip/model/Message.java   |  22 --
 .../apache/gossip/model/NotAMemberFault.java    |  29 --
 .../apache/gossip/model/PerNodeDataMessage.java |  66 ----
 .../java/org/apache/gossip/model/Response.java  |  22 --
 .../apache/gossip/model/SharedDataMessage.java  |  64 ---
 .../apache/gossip/model/ShutdownMessage.java    |  51 ---
 .../org/apache/gossip/model/SignedPayload.java  |  36 --
 .../java/org/apache/gossip/secure/KeyTool.java  |  57 ---
 .../java/org/apache/gossip/udp/Trackable.java   |  30 --
 .../gossip/udp/UdpActiveGossipMessage.java      |  49 ---
 .../apache/gossip/udp/UdpActiveGossipOk.java    |  44 ---
 .../apache/gossip/udp/UdpNotAMemberFault.java   |  46 ---
 .../gossip/udp/UdpPerNodeDataMessage.java       |  48 ---
 .../apache/gossip/udp/UdpSharedDataMessage.java |  50 ---
 src/main/resources/log4j.properties             |  20 -
 .../apache/gossip/AbstractIntegrationBase.java  |  50 ---
 src/test/java/org/apache/gossip/DataTest.java   | 238 ------------
 .../org/apache/gossip/IdAndPropertyTest.java    |  91 -----
 src/test/java/org/apache/gossip/MemberTest.java |  40 --
 .../org/apache/gossip/ShutdownDeadtimeTest.java | 146 -------
 .../org/apache/gossip/SignedMessageTest.java    | 135 -------
 .../org/apache/gossip/StartupSettingsTest.java  |  86 -----
 .../org/apache/gossip/TenNodeThreeSeedTest.java |  92 -----
 .../gossip/accrual/FailureDetectorTest.java     | 113 ------
 .../apache/gossip/crdt/GrowOnlyCounterTest.java |  54 ---
 .../org/apache/gossip/crdt/GrowOnlySetTest.java |  38 --
 .../java/org/apache/gossip/crdt/OrSetTest.java  | 115 ------
 .../apache/gossip/manager/DataReaperTest.java   | 104 -----
 .../manager/GossipManagerBuilderTest.java       | 121 ------
 .../gossip/manager/RingPersistenceTest.java     |  64 ---
 .../gossip/manager/UserDataPersistenceTest.java | 114 ------
 .../manager/handlers/MessageInvokerTest.java    | 178 ---------
 src/test/resources/log4j.properties             |  20 -
 169 files changed, 7126 insertions(+), 7101 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index fc368f3..fab2364 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
 .idea/
 *.iml
 *.iws
+*.ipr
 
 # Mac
 .DS_Store

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/pom.xml
----------------------------------------------------------------------
diff --git a/gossip-base/pom.xml b/gossip-base/pom.xml
new file mode 100644
index 0000000..3529bd1
--- /dev/null
+++ b/gossip-base/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.gossip</groupId>
+    <artifactId>gossip-parent</artifactId>
+    <version>0.1.3-incubating-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  
+  <name>Gossip Base</name>
+  <artifactId>gossip-base</artifactId>
+  <version>0.1.3-incubating-SNAPSHOT</version>
+  
+  <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>
+	
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/GossipSettings.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/GossipSettings.java b/gossip-base/src/main/java/org/apache/gossip/GossipSettings.java
new file mode 100644
index 0000000..6b2bf8b
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/GossipSettings.java
@@ -0,0 +1,226 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/LocalMember.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/LocalMember.java b/gossip-base/src/main/java/org/apache/gossip/LocalMember.java
new file mode 100644
index 0000000..450bce5
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/LocalMember.java
@@ -0,0 +1,71 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/Member.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/Member.java b/gossip-base/src/main/java/org/apache/gossip/Member.java
new file mode 100644
index 0000000..d04a7b6
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/Member.java
@@ -0,0 +1,166 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/RemoteMember.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/RemoteMember.java b/gossip-base/src/main/java/org/apache/gossip/RemoteMember.java
new file mode 100644
index 0000000..6b42da2
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/RemoteMember.java
@@ -0,0 +1,47 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/StartupSettings.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/StartupSettings.java b/gossip-base/src/main/java/org/apache/gossip/StartupSettings.java
new file mode 100644
index 0000000..17eaaf2
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/StartupSettings.java
@@ -0,0 +1,207 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/accrual/FailureDetector.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/accrual/FailureDetector.java b/gossip-base/src/main/java/org/apache/gossip/accrual/FailureDetector.java
new file mode 100644
index 0000000..5abd5c6
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/accrual/FailureDetector.java
@@ -0,0 +1,80 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/crdt/Crdt.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/Crdt.java b/gossip-base/src/main/java/org/apache/gossip/crdt/Crdt.java
new file mode 100644
index 0000000..8edfa8c
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/Crdt.java
@@ -0,0 +1,39 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java
new file mode 100644
index 0000000..1ac7a30
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtBiFunctionMerge.java
@@ -0,0 +1,55 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtCounter.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtCounter.java b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtCounter.java
new file mode 100644
index 0000000..cdc9445
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtCounter.java
@@ -0,0 +1,24 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtModule.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtModule.java b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtModule.java
new file mode 100644
index 0000000..cfb3f47
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtModule.java
@@ -0,0 +1,69 @@
+/*
+ * 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/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtSet.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtSet.java b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtSet.java
new file mode 100644
index 0000000..21b41da
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/CrdtSet.java
@@ -0,0 +1,26 @@
+/*
+ * 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> {
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java b/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java
new file mode 100644
index 0000000..dd1505a
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlyCounter.java
@@ -0,0 +1,119 @@
+/*
+ * 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.apache.gossip.manager.GossipManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GrowOnlyCounter implements CrdtCounter<Long, GrowOnlyCounter> {
+  
+  private final Map<String, Long> counters = new HashMap<>();
+  
+  GrowOnlyCounter(Map<String, Long> counters) {
+    this.counters.putAll(counters);
+  }
+  
+  public GrowOnlyCounter(GrowOnlyCounter growOnlyCounter, Builder builder) {
+    counters.putAll(growOnlyCounter.counters);
+    if (counters.containsKey(builder.myId)) {
+      Long newValue = counters.get(builder.myId) + builder.counter;
+      counters.replace(builder.myId, newValue);
+    } else {
+      counters.put(builder.myId, builder.counter);
+    }
+  }
+  
+  public GrowOnlyCounter(Builder builder) {
+    counters.put(builder.myId, builder.counter);
+  }
+  
+  public GrowOnlyCounter(GossipManager manager) {
+    counters.put(manager.getMyself().getId(), 0L);
+  }
+  
+  public GrowOnlyCounter(GrowOnlyCounter growOnlyCounter, GrowOnlyCounter other) {
+    counters.putAll(growOnlyCounter.counters);
+    for (Map.Entry<String, Long> entry : other.counters.entrySet()) {
+      String otherKey = entry.getKey();
+      Long otherValue = entry.getValue();
+      
+      if (counters.containsKey(otherKey)) {
+        Long newValue = Math.max(counters.get(otherKey), otherValue);
+        counters.replace(otherKey, newValue);
+      } else {
+        counters.put(otherKey, otherValue);
+      }
+    }
+  }
+  
+  @Override
+  public GrowOnlyCounter merge(GrowOnlyCounter other) {
+    return new GrowOnlyCounter(this, other);
+  }
+  
+  @Override
+  public Long value() {
+    Long globalCount = 0L;
+    for (Long increment : counters.values()) {
+      globalCount += increment;
+    }
+    return globalCount;
+  }
+  
+  @Override
+  public GrowOnlyCounter optimize() {
+    return new GrowOnlyCounter(counters);
+  }
+  
+  @Override
+  public boolean equals(Object obj) {
+    if (getClass() != obj.getClass())
+      return false;
+    GrowOnlyCounter other = (GrowOnlyCounter) obj;
+    return value().longValue() == other.value().longValue();
+  }
+  
+  @Override
+  public String toString() {
+    return "GrowOnlyCounter [counters= " + counters + ", Value=" + value() + "]";
+  }
+  
+  Map<String, Long> getCounters() {
+    return counters;
+  }
+  
+  public static class Builder {
+    
+    private final String myId;
+    
+    private Long counter;
+    
+    public Builder(GossipManager gossipManager) {
+      myId = gossipManager.getMyself().getId();
+      counter = 0L;
+    }
+    
+    public GrowOnlyCounter.Builder increment(Long count) {
+      counter += count;
+      return this;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java b/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java
new file mode 100644
index 0000000..9e2dd49
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/GrowOnlySet.java
@@ -0,0 +1,157 @@
+/*
+ * 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.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class GrowOnlySet<ElementType> implements CrdtSet<ElementType, Set<ElementType>, GrowOnlySet<ElementType>>{
+
+  private final Set<ElementType> hidden = new LinkedHashSet<>();
+  
+  @SuppressWarnings("unused")
+  /*
+   * Used by SerDe
+   */
+  private GrowOnlySet(){
+    
+  }
+  
+  public GrowOnlySet(Set<ElementType> c){
+    hidden.addAll(c);
+  }
+  
+  public GrowOnlySet(Collection<ElementType> c){
+    hidden.addAll(c);
+  }
+  
+  public GrowOnlySet(GrowOnlySet<ElementType> first, GrowOnlySet<ElementType> second){
+    hidden.addAll(first.value());
+    hidden.addAll(second.value());
+  }
+  
+  @Override
+  public GrowOnlySet<ElementType> merge(GrowOnlySet<ElementType> other) {
+    return new GrowOnlySet<>(this, other);
+  }
+
+  @Override
+  public Set<ElementType> value() {
+    Set<ElementType> copy = new LinkedHashSet<>();
+    copy.addAll(hidden);
+    return Collections.unmodifiableSet(copy);
+  }
+  
+  @Override
+  public GrowOnlySet<ElementType> optimize() {
+    return new GrowOnlySet<>(hidden);
+  }
+
+  public int size() {
+    return hidden.size();
+  }
+
+  public boolean isEmpty() {
+    return hidden.isEmpty();
+  }
+
+  public boolean contains(Object o) {
+    return hidden.contains(o);
+  }
+
+  public Iterator<ElementType> iterator() {
+    Set<ElementType> copy = new HashSet<>();
+    copy.addAll(hidden);
+    return copy.iterator();
+  }
+
+  public Object[] toArray() {
+    return hidden.toArray();
+  }
+
+  public <T> T[] toArray(T[] a) {
+    return hidden.toArray(a);
+  }
+
+  public boolean add(ElementType e) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean remove(Object o) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean containsAll(Collection<?> c) {
+    return hidden.containsAll(c);
+  }
+
+  public boolean addAll(Collection<? extends ElementType> c) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean retainAll(Collection<?> c) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean removeAll(Collection<?> c) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String toString() {
+    return "GrowOnlySet [hidden=" + hidden + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((hidden == null) ? 0 : hidden.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    @SuppressWarnings("rawtypes")
+    GrowOnlySet other = (GrowOnlySet) obj;
+    if (hidden == null) {
+      if (other.hidden != null)
+        return false;
+    } else if (!hidden.equals(other.hidden))
+      return false;
+    return true;
+  }
+
+  Set<ElementType> getElements(){
+    return hidden;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/crdt/OrSet.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/crdt/OrSet.java b/gossip-base/src/main/java/org/apache/gossip/crdt/OrSet.java
new file mode 100644
index 0000000..f84dbc7
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/crdt/OrSet.java
@@ -0,0 +1,304 @@
+/*
+ * 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.*;
+import java.util.Map.Entry;
+import java.util.function.BiConsumer;
+
+import org.apache.gossip.crdt.OrSet.Builder.Operation;
+
+/*
+ * A immutable set 
+ */
+public class OrSet<E>  implements Crdt<Set<E>, OrSet<E>> {
+  
+  private final Map<E, Set<UUID>> elements = new HashMap<>();
+  private final Map<E, Set<UUID>> tombstones = new HashMap<>();
+  private final transient Set<E> val;
+  
+  public OrSet(){
+    val = computeValue();
+  }
+  
+  OrSet(Map<E, Set<UUID>> elements, Map<E, Set<UUID>> tombstones){
+    this.elements.putAll(elements);
+    this.tombstones.putAll(tombstones);
+    val = computeValue();
+  }
+  
+  @SafeVarargs
+  public OrSet(E ... elements){
+    for (E e: elements){
+      internalAdd(e);
+    }
+    val = computeValue();
+  }
+  
+  public OrSet(Builder<E>builder){
+    for (Builder<E>.OrSetElement<E> e: builder.elements){
+      if (e.operation == Operation.ADD){
+        internalAdd(e.element);
+      } else {
+        internalRemove(e.element);
+      }
+    }
+    val = computeValue();
+  }
+  
+  /**
+   * This constructor is the way to remove elements from an existing set
+   * @param set
+   * @param builder 
+   */
+  public OrSet(OrSet<E> set, Builder<E> builder){
+    elements.putAll(set.elements);
+    tombstones.putAll(set.tombstones);
+    for (Builder<E>.OrSetElement<E> e: builder.elements){
+      if (e.operation == Operation.ADD){
+        internalAdd(e.element);
+      } else {
+        internalRemove(e.element);
+      }
+    }
+    val = computeValue();
+  }
+
+  static Set<UUID> mergeSets(Set<UUID> a, Set<UUID> b) {
+    if ((a == null || a.isEmpty()) && (b == null || b.isEmpty())) {
+      return null;
+    }
+    Set<UUID> res = new HashSet<>(a);
+    res.addAll(b);
+    return res;
+  }
+
+  private void internalSetMerge(Map<E, Set<UUID>> map, E key, Set<UUID> value) {
+    if (value == null) {
+      return;
+    }
+    map.merge(key, value, OrSet::mergeSets);
+  }
+
+  public OrSet(OrSet<E> left, OrSet<E> right){
+    BiConsumer<Map<E, Set<UUID>>, Map<E, Set<UUID>>> internalMerge = (items, other) -> {
+      for (Entry<E, Set<UUID>> l : other.entrySet()){
+        internalSetMerge(items, l.getKey(), l.getValue());
+      }
+    };
+
+    internalMerge.accept(elements, left.elements);
+    internalMerge.accept(elements, right.elements);
+    internalMerge.accept(tombstones, left.tombstones);
+    internalMerge.accept(tombstones, right.tombstones);
+
+    val = computeValue();
+  }
+  
+  public OrSet.Builder<E> builder(){
+    return new OrSet.Builder<>();
+  }
+  
+  @Override
+  public OrSet<E> merge(OrSet<E> other) {
+    return new OrSet<E>(this, other);
+  }
+  
+  private void internalAdd(E element) {
+    Set<UUID> toMerge = new HashSet<>();
+    toMerge.add(UUID.randomUUID());
+    internalSetMerge(elements, element, toMerge);
+  }
+  
+  private void internalRemove(E element){
+    internalSetMerge(tombstones, element, elements.get(element));
+  }
+
+  /*
+   * Computes the live values by analyzing the elements and tombstones
+   */
+  private Set<E> computeValue(){
+    Set<E> values = new HashSet<>();
+    for (Entry<E, Set<UUID>> entry: elements.entrySet()){
+      Set<UUID> deleteIds = tombstones.get(entry.getKey());
+      // if not all tokens for current element are in tombstones
+      if (deleteIds == null || !deleteIds.containsAll(entry.getValue())) {
+        values.add(entry.getKey());
+      }
+    }
+    return values;
+  }
+  
+  @Override
+  public Set<E> value() {
+    return val;
+  }
+
+  @Override
+  public OrSet<E> optimize() {
+    return this;
+  }
+  
+  public static class Builder<E> {
+    public static enum Operation {
+      ADD, REMOVE
+    };
+
+    private class OrSetElement<EL> {
+      EL element;
+      Operation operation;
+
+      private OrSetElement(EL element, Operation operation) {
+        this.element = element;
+        this.operation = operation;
+      }
+    }
+
+    private List<OrSetElement<E>> elements = new ArrayList<>();
+
+    public Builder<E> add(E element) {
+      elements.add(new OrSetElement<E>(element, Operation.ADD));
+      return this;
+    }
+
+    public Builder<E> remove(E element) {
+      elements.add(new OrSetElement<E>(element, Operation.REMOVE));
+      return this;
+    }
+
+    public Builder<E> mutate(E element, Operation operation) {
+      elements.add(new OrSetElement<E>(element, operation));
+      return this;
+    }
+  }
+
+  
+  public int size() {
+    return value().size();
+  }
+
+  
+  public boolean isEmpty() {
+    return value().size() == 0;
+  }
+
+  
+  public boolean contains(Object o) {
+    return value().contains(o);
+  }
+
+  
+  public Iterator<E> iterator() {
+    Iterator<E> managed = value().iterator();
+    return new Iterator<E>() {
+
+      @Override
+      public void remove() {
+        throw new IllegalArgumentException();
+      }
+
+      @Override
+      public boolean hasNext() {
+        return managed.hasNext();
+      }
+
+      @Override
+      public E next() {
+        return managed.next();
+      }
+      
+    };
+  }
+
+  public Object[] toArray() {
+    return value().toArray();
+  }
+
+  public <T> T[] toArray(T[] a) {
+    return value().toArray(a);
+  }
+
+  public boolean add(E e) {
+    throw new IllegalArgumentException("Can not add");
+  }
+
+
+  public boolean remove(Object o) {
+    throw new IllegalArgumentException();
+  }
+
+  public boolean containsAll(Collection<?> c) {
+    return this.value().containsAll(c);
+  }
+
+  public boolean addAll(Collection<? extends E> c) {
+    throw new IllegalArgumentException();
+  }
+
+  public boolean retainAll(Collection<?> c) {
+    throw new IllegalArgumentException();
+  }
+
+  public boolean removeAll(Collection<?> c) {
+    throw new IllegalArgumentException();
+  }
+
+  public void clear() {
+    throw new IllegalArgumentException();
+  }
+
+  @Override
+  public String toString() {
+    return "OrSet [elements=" + elements + ", tombstones=" + tombstones + "]" ;
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((value() == null) ? 0 : value().hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    @SuppressWarnings("rawtypes")
+    OrSet other = (OrSet) obj;
+    if (elements == null) {
+      if (other.elements != null)
+        return false;
+    } else if (!value().equals(other.value()))
+      return false;
+    return true;
+  }
+
+  Map<E, Set<UUID>> getElements() {
+    return elements;
+  }
+
+  Map<E, Set<UUID>> getTombstones() {
+    return tombstones;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/event/GossipListener.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/event/GossipListener.java b/gossip-base/src/main/java/org/apache/gossip/event/GossipListener.java
new file mode 100644
index 0000000..9b33dab
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/event/GossipListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.event;
+
+import org.apache.gossip.Member;
+
+public interface GossipListener {
+  void gossipEvent(Member member, GossipState state);
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/event/GossipState.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/event/GossipState.java b/gossip-base/src/main/java/org/apache/gossip/event/GossipState.java
new file mode 100644
index 0000000..3b76c9e
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/event/GossipState.java
@@ -0,0 +1,28 @@
+/*
+ * 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.event;
+
+public enum GossipState {
+  UP("up"), DOWN("down");
+  @SuppressWarnings("unused")
+  private final String state;
+
+  private GossipState(String state) {
+    this.state = state;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java b/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
new file mode 100644
index 0000000..497894c
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
@@ -0,0 +1,62 @@
+/*
+ * 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.examples;
+
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.RemoteMember;
+import org.apache.gossip.manager.DatacenterRackAwareActiveGossiper;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+
+public class StandAloneDatacenterAndRack {
+
+  public static void main (String [] args) throws UnknownHostException, InterruptedException {
+    GossipSettings s = new GossipSettings();
+    s.setWindowSize(1000);
+    s.setGossipInterval(100);
+    s.setActiveGossipClass(DatacenterRackAwareActiveGossiper.class.getName());
+    Map<String, String> gossipProps = new HashMap<>();
+    gossipProps.put("sameRackGossipIntervalMs", "2000");
+    gossipProps.put("differentDatacenterGossipIntervalMs", "10000");
+    s.setActiveGossipProperties(gossipProps);
+    Map<String, String> props = new HashMap<>();
+    props.put(DatacenterRackAwareActiveGossiper.DATACENTER, args[4]);
+    props.put(DatacenterRackAwareActiveGossiper.RACK, args[5]);
+    GossipManager manager = GossipManagerBuilder.newBuilder()
+            .cluster("mycluster")
+            .uri(URI.create(args[0]))
+            .id(args[1])
+            .gossipSettings(s)
+            .gossipMembers(Arrays.asList(new RemoteMember("mycluster", URI.create(args[2]), args[3])))
+            .properties(props)
+            .build();
+    manager.init();
+    while (true){
+      System.out.println("Live: " + manager.getLiveMembers());
+      System.out.println("Dead: " + manager.getDeadMembers());
+      Thread.sleep(2000);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNode.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNode.java b/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNode.java
new file mode 100644
index 0000000..93421b1
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNode.java
@@ -0,0 +1,47 @@
+/*
+ * 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.examples;
+
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.RemoteMember;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+
+public class StandAloneNode {
+  public static void main (String [] args) throws UnknownHostException, InterruptedException{
+    GossipSettings s = new GossipSettings();
+    s.setWindowSize(1000);
+    s.setGossipInterval(100);
+    GossipManager gossipService = GossipManagerBuilder.newBuilder()
+            .cluster("mycluster")
+            .uri(URI.create(args[0]))
+            .id(args[1])
+            .gossipMembers(Arrays.asList( new RemoteMember("mycluster", URI.create(args[2]), args[3])))
+            .gossipSettings(s)
+            .build();
+    gossipService.init();
+    while (true){
+      System.out.println("Live: " + gossipService.getLiveMembers());
+      System.out.println("Dead: " + gossipService.getDeadMembers());
+      Thread.sleep(2000);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java b/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
new file mode 100644
index 0000000..d78cf5e
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.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.examples;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.util.Arrays;
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.RemoteMember;
+import org.apache.gossip.crdt.GrowOnlyCounter;
+import org.apache.gossip.crdt.OrSet;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.manager.GossipManagerBuilder;
+import org.apache.gossip.model.SharedDataMessage;
+
+public class StandAloneNodeCrdtOrSet {
+  public static void main (String [] args) throws InterruptedException, IOException{
+    GossipSettings s = new GossipSettings();
+    s.setWindowSize(1000);
+    s.setGossipInterval(100);
+    GossipManager gossipService = GossipManagerBuilder.newBuilder()
+            .cluster("mycluster")
+            .uri(URI.create(args[0]))
+            .id(args[1])
+            .gossipMembers(Arrays.asList( new RemoteMember("mycluster", URI.create(args[2]), args[3])))
+            .gossipSettings(s)
+            .build();
+    gossipService.init();
+    
+    new Thread(() -> {
+      while (true){
+      System.out.println("Live: " + gossipService.getLiveMembers());
+      System.out.println("Dead: " + gossipService.getDeadMembers());
+      System.out.println("---------- " + (gossipService.findCrdt("abc") == null ? "": 
+          gossipService.findCrdt("abc").value()));
+      System.out.println("********** " + gossipService.findCrdt("abc"));
+      System.out.println("^^^^^^^^^^ " + (gossipService.findCrdt("def") == null ? "": 
+        gossipService.findCrdt("def").value()));
+      System.out.println("$$$$$$$$$$ " + gossipService.findCrdt("def"));
+      try {
+        Thread.sleep(2000);
+      } catch (Exception e) {}
+      }
+    }).start();
+    
+    String line = null;
+    try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))){
+      while ( (line = br.readLine()) != null){
+        System.out.println(line);
+        char op = line.charAt(0);
+        String val = line.substring(2);
+        if (op == 'a'){
+          addData(val, gossipService);
+        } else if (op == 'r') {
+          removeData(val, gossipService);
+        } else if (op == 'g'){
+          gcount(val, gossipService);
+        }
+      }
+    }
+  }
+  
+  private static void gcount(String val, GossipManager gossipManager){
+    GrowOnlyCounter c = (GrowOnlyCounter) gossipManager.findCrdt("def");
+    Long l = Long.valueOf(val);
+    if (c == null){
+      c = new GrowOnlyCounter(new GrowOnlyCounter.Builder(gossipManager).increment((l)));
+    } else {
+      c = new GrowOnlyCounter(c, new GrowOnlyCounter.Builder(gossipManager).increment((l)));
+    }
+    SharedDataMessage m = new SharedDataMessage();
+    m.setExpireAt(Long.MAX_VALUE);
+    m.setKey("def");
+    m.setPayload(c);
+    m.setTimestamp(System.currentTimeMillis());
+    gossipManager.merge(m);
+  }
+  
+  private static void removeData(String val, GossipManager gossipService){
+    @SuppressWarnings("unchecked")
+    OrSet<String> s = (OrSet<String>) gossipService.findCrdt("abc");
+    SharedDataMessage m = new SharedDataMessage();
+    m.setExpireAt(Long.MAX_VALUE);
+    m.setKey("abc");
+    m.setPayload(new OrSet<String>(s , new OrSet.Builder<String>().remove(val)));
+    m.setTimestamp(System.currentTimeMillis());
+    gossipService.merge(m);
+  }
+  
+  private static void addData(String val, GossipManager gossipService){
+    SharedDataMessage m = new SharedDataMessage();
+    m.setExpireAt(Long.MAX_VALUE);
+    m.setKey("abc");
+    m.setPayload(new OrSet<String>(val));
+    m.setTimestamp(System.currentTimeMillis());
+    gossipService.merge(m);
+  }
+}


[6/7] incubator-gossip git commit: GOSSIP-78 refactor into a multi-module maven project

Posted by ec...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java b/gossip-base/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java
new file mode 100644
index 0000000..b73550e
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/AbstractActiveGossiper.java
@@ -0,0 +1,171 @@
+/*
+ * 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.util.Map.Entry;
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.gossip.LocalMember;
+import org.apache.gossip.model.ActiveGossipOk;
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.Member;
+import org.apache.gossip.model.Response;
+import org.apache.gossip.model.SharedDataMessage;
+import org.apache.gossip.model.ShutdownMessage;
+import org.apache.gossip.udp.UdpActiveGossipMessage;
+import org.apache.gossip.udp.UdpPerNodeDataMessage;
+import org.apache.gossip.udp.UdpSharedDataMessage;
+import org.apache.log4j.Logger;
+
+import static com.codahale.metrics.MetricRegistry.name;
+
+/**
+ * The ActiveGossipThread is sends information. Pick a random partner and send the membership list to that partner
+ */
+public abstract class AbstractActiveGossiper {
+
+  protected static final Logger LOGGER = Logger.getLogger(AbstractActiveGossiper.class);
+  
+  protected final GossipManager gossipManager;
+  protected final GossipCore gossipCore;
+  private final Histogram sharedDataHistogram;
+  private final Histogram sendPerNodeDataHistogram;
+  private final Histogram sendMembershipHistorgram;
+  private final Random random;
+
+  public AbstractActiveGossiper(GossipManager gossipManager, GossipCore gossipCore, MetricRegistry registry) {
+    this.gossipManager = gossipManager;
+    this.gossipCore = gossipCore;
+    sharedDataHistogram = registry.histogram(name(AbstractActiveGossiper.class, "sharedDataHistogram-time"));
+    sendPerNodeDataHistogram = registry.histogram(name(AbstractActiveGossiper.class, "sendPerNodeDataHistogram-time"));
+    sendMembershipHistorgram = registry.histogram(name(AbstractActiveGossiper.class, "sendMembershipHistorgram-time"));
+    random = new Random();
+  }
+
+  public void init() {
+
+  }
+  
+  public void shutdown() {
+
+  }
+
+  public final void sendShutdownMessage(LocalMember me, LocalMember target){
+    if (target == null){
+      return;
+    }
+    ShutdownMessage m = new ShutdownMessage();
+    m.setNodeId(me.getId());
+    m.setShutdownAtNanos(gossipManager.getClock().nanoTime());
+    gossipCore.sendOneWay(m, target.getUri());
+  }
+  
+  public final void sendSharedData(LocalMember me, LocalMember member){
+    if (member == null){
+      return;
+    }
+    long startTime = System.currentTimeMillis();
+    for (Entry<String, SharedDataMessage> innerEntry : gossipCore.getSharedData().entrySet()){
+      UdpSharedDataMessage message = new UdpSharedDataMessage();
+      message.setUuid(UUID.randomUUID().toString());
+      message.setUriFrom(me.getId());
+      message.setExpireAt(innerEntry.getValue().getExpireAt());
+      message.setKey(innerEntry.getValue().getKey());
+      message.setNodeId(innerEntry.getValue().getNodeId());
+      message.setTimestamp(innerEntry.getValue().getTimestamp());
+      message.setPayload(innerEntry.getValue().getPayload());
+      gossipCore.sendOneWay(message, member.getUri());
+    }
+    sharedDataHistogram.update(System.currentTimeMillis() - startTime);
+  }
+  
+  public final void sendPerNodeData(LocalMember me, LocalMember member){
+    if (member == null){
+      return;
+    }
+    long startTime = System.currentTimeMillis();
+    for (Entry<String, ConcurrentHashMap<String, PerNodeDataMessage>> entry : gossipCore.getPerNodeData().entrySet()){
+      for (Entry<String, PerNodeDataMessage> innerEntry : entry.getValue().entrySet()){
+        UdpPerNodeDataMessage message = new UdpPerNodeDataMessage();
+        message.setUuid(UUID.randomUUID().toString());
+        message.setUriFrom(me.getId());
+        message.setExpireAt(innerEntry.getValue().getExpireAt());
+        message.setKey(innerEntry.getValue().getKey());
+        message.setNodeId(innerEntry.getValue().getNodeId());
+        message.setTimestamp(innerEntry.getValue().getTimestamp());
+        message.setPayload(innerEntry.getValue().getPayload());
+        gossipCore.sendOneWay(message, member.getUri());   
+      }
+    }
+    sendPerNodeDataHistogram.update(System.currentTimeMillis() - startTime);
+  }
+    
+  /**
+   * Performs the sending of the membership list, after we have incremented our own heartbeat.
+   */
+  protected void sendMembershipList(LocalMember me, LocalMember member) {
+    if (member == null){
+      return;
+    }
+    long startTime = System.currentTimeMillis();
+    me.setHeartbeat(System.nanoTime());
+    UdpActiveGossipMessage message = new UdpActiveGossipMessage();
+    message.setUriFrom(gossipManager.getMyself().getUri().toASCIIString());
+    message.setUuid(UUID.randomUUID().toString());
+    message.getMembers().add(convert(me));
+    for (LocalMember other : gossipManager.getMembers().keySet()) {
+      message.getMembers().add(convert(other));
+    }
+    Response r = gossipCore.send(message, member.getUri());
+    if (r instanceof ActiveGossipOk){
+      //maybe count metrics here
+    } else {
+      LOGGER.debug("Message " + message + " generated response " + r);
+    }
+    sendMembershipHistorgram.update(System.currentTimeMillis() - startTime);
+  }
+    
+  protected final Member convert(LocalMember member){
+    Member gm = new Member();
+    gm.setCluster(member.getClusterName());
+    gm.setHeartbeat(member.getHeartbeat());
+    gm.setUri(member.getUri().toASCIIString());
+    gm.setId(member.getId());
+    gm.setProperties(member.getProperties());
+    return gm;
+  }
+  
+  /**
+   * 
+   * @param memberList
+   *          An immutable list
+   * @return The chosen LocalGossipMember to gossip with.
+   */
+  protected LocalMember selectPartner(List<LocalMember> memberList) {
+    LocalMember member = null;
+    if (memberList.size() > 0) {
+      int randomNeighborIndex = random.nextInt(memberList.size());
+      member = memberList.get(randomNeighborIndex);
+    }
+    return member;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/Clock.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/Clock.java b/gossip-base/src/main/java/org/apache/gossip/manager/Clock.java
new file mode 100644
index 0000000..6629c62
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/Clock.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+public interface Clock {
+
+  long currentTimeMillis();
+  long nanoTime();
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/DataReaper.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/DataReaper.java b/gossip-base/src/main/java/org/apache/gossip/manager/DataReaper.java
new file mode 100644
index 0000000..8175a1b
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/DataReaper.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.SharedDataMessage;
+
+/**
+ * We wish to periodically sweep user data and remove entries past their timestamp. This
+ * implementation periodically sweeps through the data and removes old entries. While it might make
+ * sense to use a more specific high performance data-structure to handle eviction, keep in mind
+ * that we are not looking to store a large quantity of data as we currently have to transmit this
+ * data cluster wide.
+ */
+public class DataReaper {
+
+  private final GossipCore gossipCore;
+  private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);
+  private final Clock clock;
+  
+  public DataReaper(GossipCore gossipCore, Clock clock){
+    this.gossipCore = gossipCore;
+    this.clock = clock;
+  }
+  
+  public void init(){
+    Runnable reapPerNodeData = () -> {
+      runPerNodeOnce();
+      runSharedOnce();
+    };
+    scheduledExecutor.scheduleAtFixedRate(reapPerNodeData, 0, 5, TimeUnit.SECONDS);
+  }
+  
+  void runSharedOnce(){
+    for (Entry<String, SharedDataMessage> entry : gossipCore.getSharedData().entrySet()){
+      if (entry.getValue().getExpireAt() < clock.currentTimeMillis()){
+        gossipCore.getSharedData().remove(entry.getKey(), entry.getValue());
+      }
+    }
+  }
+  
+  void runPerNodeOnce(){
+    for (Entry<String, ConcurrentHashMap<String, PerNodeDataMessage>> node : gossipCore.getPerNodeData().entrySet()){
+      reapData(node.getValue());
+    }
+  }
+  
+  void reapData(ConcurrentHashMap<String, PerNodeDataMessage> concurrentHashMap){
+    for (Entry<String, PerNodeDataMessage> entry : concurrentHashMap.entrySet()){
+      if (entry.getValue().getExpireAt() < clock.currentTimeMillis()){
+        concurrentHashMap.remove(entry.getKey(), entry.getValue());
+      }
+    }
+  }
+  
+  public void close(){
+    scheduledExecutor.shutdown();
+    try {
+      scheduledExecutor.awaitTermination(1, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java b/gossip-base/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java
new file mode 100644
index 0000000..2f489a2
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/DatacenterRackAwareActiveGossiper.java
@@ -0,0 +1,244 @@
+/*
+ * 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.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.gossip.LocalMember;
+
+import com.codahale.metrics.MetricRegistry;
+
+/**
+ * Sends gossip traffic at different rates to other racks and data-centers.
+ * This implementation controls the rate at which gossip traffic is shared. 
+ * There are two constructs Datacenter and Rack. It is assumed that bandwidth and latency is higher
+ * in the rack than in the the datacenter. We can adjust the rate at which we send messages to each group.
+ * 
+ */
+public class DatacenterRackAwareActiveGossiper extends AbstractActiveGossiper {
+
+  public static final String DATACENTER = "datacenter";
+  public static final String RACK = "rack";
+  
+  private int sameRackGossipIntervalMs = 100;
+  private int sameDcGossipIntervalMs = 500;
+  private int differentDatacenterGossipIntervalMs = 1000;
+  private int randomDeadMemberSendIntervalMs = 250;
+  
+  private ScheduledExecutorService scheduledExecutorService;
+  private final BlockingQueue<Runnable> workQueue;
+  private ThreadPoolExecutor threadService;
+  
+  public DatacenterRackAwareActiveGossiper(GossipManager gossipManager, GossipCore gossipCore,
+          MetricRegistry registry) {
+    super(gossipManager, gossipCore, registry);
+    scheduledExecutorService = Executors.newScheduledThreadPool(2);
+    workQueue = new ArrayBlockingQueue<Runnable>(1024);
+    threadService = new ThreadPoolExecutor(1, 30, 1, TimeUnit.SECONDS, workQueue,
+            new ThreadPoolExecutor.DiscardOldestPolicy());
+    try {
+      sameRackGossipIntervalMs = Integer.parseInt(gossipManager.getSettings()
+              .getActiveGossipProperties().get("sameRackGossipIntervalMs"));
+    } catch (RuntimeException ex) { }
+    try {
+      sameDcGossipIntervalMs = Integer.parseInt(gossipManager.getSettings()
+              .getActiveGossipProperties().get("sameDcGossipIntervalMs"));
+    } catch (RuntimeException ex) { }
+    try {
+      differentDatacenterGossipIntervalMs = Integer.parseInt(gossipManager.getSettings()
+              .getActiveGossipProperties().get("differentDatacenterGossipIntervalMs"));
+    } catch (RuntimeException ex) { }
+    try {
+      randomDeadMemberSendIntervalMs = Integer.parseInt(gossipManager.getSettings()
+              .getActiveGossipProperties().get("randomDeadMemberSendIntervalMs"));
+    } catch (RuntimeException ex) { }
+  }
+
+  @Override
+  public void init() {
+    super.init();
+    //same rack
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+      threadService.execute(() -> sendToSameRackMember()), 
+      0, sameRackGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+      threadService.execute(() -> sendToSameRackMemberPerNode()), 
+      0, sameRackGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+      threadService.execute(() -> sendToSameRackShared()), 
+      0, sameRackGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    //same dc different rack
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+      threadService.execute(() -> sameDcDiffernetRackMember()), 
+      0, sameDcGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+    threadService.execute(() -> sameDcDiffernetRackPerNode()), 
+    0, sameDcGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+    threadService.execute(() -> sameDcDiffernetRackShared()), 
+    0, sameDcGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    //different dc
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+      threadService.execute(() -> differentDcMember()), 
+      0, differentDatacenterGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+    threadService.execute(() -> differentDcPerNode()), 
+    0, differentDatacenterGossipIntervalMs, TimeUnit.MILLISECONDS);
+  
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+    threadService.execute(() -> differentDcShared()), 
+    0, differentDatacenterGossipIntervalMs, TimeUnit.MILLISECONDS);
+    
+    //the dead
+    scheduledExecutorService.scheduleAtFixedRate(() -> 
+      threadService.execute(() -> sendToDeadMember()), 
+      0, randomDeadMemberSendIntervalMs, TimeUnit.MILLISECONDS);
+    
+  }
+
+  private void sendToDeadMember() {
+    sendMembershipList(gossipManager.getMyself(), selectPartner(gossipManager.getDeadMembers()));
+  }
+  
+  private List<LocalMember> differentDataCenter(){
+    String myDc = gossipManager.getMyself().getProperties().get(DATACENTER);
+    String rack = gossipManager.getMyself().getProperties().get(RACK);
+    if (myDc == null|| rack == null){
+      return Collections.emptyList();
+    }
+    List<LocalMember> notMyDc = new ArrayList<LocalMember>(10);
+    for (LocalMember i : gossipManager.getLiveMembers()){
+      if (!myDc.equals(i.getProperties().get(DATACENTER))){
+        notMyDc.add(i);
+      }
+    }
+    return notMyDc;
+  }
+  
+  private List<LocalMember> sameDatacenterDifferentRack(){
+    String myDc = gossipManager.getMyself().getProperties().get(DATACENTER);
+    String rack = gossipManager.getMyself().getProperties().get(RACK);
+    if (myDc == null|| rack == null){
+      return Collections.emptyList();
+    }
+    List<LocalMember> notMyDc = new ArrayList<LocalMember>(10);
+    for (LocalMember i : gossipManager.getLiveMembers()){
+      if (myDc.equals(i.getProperties().get(DATACENTER)) && !rack.equals(i.getProperties().get(RACK))){
+        notMyDc.add(i);
+      }
+    }
+    return notMyDc;
+  }
+    
+  private List<LocalMember> sameRackNodes(){
+    String myDc = gossipManager.getMyself().getProperties().get(DATACENTER);
+    String rack = gossipManager.getMyself().getProperties().get(RACK);
+    if (myDc == null|| rack == null){
+      return Collections.emptyList();
+    }
+    List<LocalMember> sameDcAndRack = new ArrayList<LocalMember>(10);
+    for (LocalMember i : gossipManager.getLiveMembers()){
+      if (myDc.equals(i.getProperties().get(DATACENTER))
+              && rack.equals(i.getProperties().get(RACK))){
+        sameDcAndRack.add(i);
+      }
+    }
+    return sameDcAndRack;
+  }
+
+  private void sendToSameRackMember() {
+    LocalMember i = selectPartner(sameRackNodes());
+    sendMembershipList(gossipManager.getMyself(), i);
+  }
+  
+  private void sendToSameRackMemberPerNode() {
+    sendPerNodeData(gossipManager.getMyself(), selectPartner(sameRackNodes()));
+  }
+  
+  private void sendToSameRackShared() {
+    sendSharedData(gossipManager.getMyself(), selectPartner(sameRackNodes()));
+  }
+  
+  private void differentDcMember() {
+    sendMembershipList(gossipManager.getMyself(), selectPartner(differentDataCenter()));
+  }
+  
+  private void differentDcPerNode() {
+    sendPerNodeData(gossipManager.getMyself(), selectPartner(differentDataCenter()));
+  }
+  
+  private void differentDcShared() {
+    sendSharedData(gossipManager.getMyself(), selectPartner(differentDataCenter()));
+  }
+  
+  private void sameDcDiffernetRackMember() {
+    sendMembershipList(gossipManager.getMyself(), selectPartner(sameDatacenterDifferentRack()));
+  }
+  
+  private void sameDcDiffernetRackPerNode() {
+    sendPerNodeData(gossipManager.getMyself(), selectPartner(sameDatacenterDifferentRack()));
+  }
+  
+  private void sameDcDiffernetRackShared() {
+    sendSharedData(gossipManager.getMyself(), selectPartner(sameDatacenterDifferentRack()));
+  }
+  
+  @Override
+  public void shutdown() {
+    super.shutdown();
+    scheduledExecutorService.shutdown();
+    try {
+      scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      LOGGER.debug("Issue during shutdown", e);
+    }
+    sendShutdownMessage();
+    threadService.shutdown();
+    try {
+      threadService.awaitTermination(5, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      LOGGER.debug("Issue during shutdown", e);
+    }
+  }
+  
+  /**
+   * sends an optimistic shutdown message to several clusters nodes
+   */
+  protected void sendShutdownMessage(){
+    List<LocalMember> l = gossipManager.getLiveMembers();
+    int sendTo = l.size() < 3 ? 1 : l.size() / 3;
+    for (int i = 0; i < sendTo; i++) {
+      threadService.execute(() -> sendShutdownMessage(gossipManager.getMyself(), selectPartner(l)));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/GossipCore.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/GossipCore.java b/gossip-base/src/main/java/org/apache/gossip/manager/GossipCore.java
new file mode 100644
index 0000000..f53419d
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/GossipCore.java
@@ -0,0 +1,387 @@
+/*
+ * 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.Gauge;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.gossip.Member;
+import org.apache.gossip.LocalMember;
+import org.apache.gossip.RemoteMember;
+import org.apache.gossip.crdt.Crdt;
+import org.apache.gossip.event.GossipState;
+import org.apache.gossip.model.*;
+import org.apache.gossip.udp.Trackable;
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.URI;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.*;
+
+public class GossipCore implements GossipCoreConstants {
+
+  class LatchAndBase {
+    private final CountDownLatch latch;
+    private volatile Base base;
+    
+    LatchAndBase(){
+      latch = new CountDownLatch(1);
+    }
+    
+  }
+  public static final Logger LOGGER = Logger.getLogger(GossipCore.class);
+  private final GossipManager gossipManager;
+  private ConcurrentHashMap<String, LatchAndBase> requests;
+  private ThreadPoolExecutor service;
+  private final ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> perNodeData;
+  private final ConcurrentHashMap<String, SharedDataMessage> sharedData;
+  private final BlockingQueue<Runnable> workQueue;
+  private final PKCS8EncodedKeySpec privKeySpec;
+  private final PrivateKey privKey;
+  private final Meter messageSerdeException;
+  private final Meter tranmissionException;
+  private final Meter tranmissionSuccess;
+
+  public GossipCore(GossipManager manager, MetricRegistry metrics){
+    this.gossipManager = manager;
+    requests = new ConcurrentHashMap<>();
+    workQueue = new ArrayBlockingQueue<>(1024);
+    service = new ThreadPoolExecutor(1, 5, 1, TimeUnit.SECONDS, workQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
+    perNodeData = new ConcurrentHashMap<>();
+    sharedData = new ConcurrentHashMap<>();
+    metrics.register(WORKQUEUE_SIZE, (Gauge<Integer>)() -> workQueue.size());
+    metrics.register(PER_NODE_DATA_SIZE, (Gauge<Integer>)() -> perNodeData.size());
+    metrics.register(SHARED_DATA_SIZE, (Gauge<Integer>)() ->  sharedData.size());
+    metrics.register(REQUEST_SIZE, (Gauge<Integer>)() ->  requests.size());
+    metrics.register(THREADPOOL_ACTIVE, (Gauge<Integer>)() ->  service.getActiveCount());
+    metrics.register(THREADPOOL_SIZE, (Gauge<Integer>)() ->  service.getPoolSize());
+    messageSerdeException = metrics.meter(MESSAGE_SERDE_EXCEPTION);
+    tranmissionException = metrics.meter(MESSAGE_TRANSMISSION_EXCEPTION);
+    tranmissionSuccess = metrics.meter(MESSAGE_TRANSMISSION_SUCCESS);
+
+    if (manager.getSettings().isSignMessages()){
+      File privateKey = new File(manager.getSettings().getPathToKeyStore(), manager.getMyself().getId());
+      File publicKey = new File(manager.getSettings().getPathToKeyStore(), manager.getMyself().getId() + ".pub");
+      if (!privateKey.exists()){
+        throw new IllegalArgumentException("private key not found " + privateKey);
+      }
+      if (!publicKey.exists()){
+        throw new IllegalArgumentException("public key not found " + publicKey);
+      }
+      try (FileInputStream keyfis = new FileInputStream(privateKey)) {
+        byte[] encKey = new byte[keyfis.available()];
+        keyfis.read(encKey);
+        keyfis.close();
+        privKeySpec = new PKCS8EncodedKeySpec(encKey);
+        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+        privKey = keyFactory.generatePrivate(privKeySpec);
+      } catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {
+        throw new RuntimeException("failed hard", e);
+      }
+    } else {
+      privKeySpec = null;
+      privKey = null;
+    }
+  }
+
+  private byte [] sign(byte [] bytes){
+    Signature dsa;
+    try {
+      dsa = Signature.getInstance("SHA1withDSA", "SUN");
+      dsa.initSign(privKey);
+      dsa.update(bytes);
+      return dsa.sign();
+    } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | SignatureException e) {
+      throw new RuntimeException(e);
+    } 
+  }
+
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  public void addSharedData(SharedDataMessage message) {
+    while (true){
+      SharedDataMessage previous = sharedData.putIfAbsent(message.getKey(), message);
+      if (previous == null){
+        return;
+      }
+      if (message.getPayload() instanceof Crdt){
+        SharedDataMessage merged = new SharedDataMessage();
+        merged.setExpireAt(message.getExpireAt());
+        merged.setKey(message.getKey());
+        merged.setNodeId(message.getNodeId());
+        merged.setTimestamp(message.getTimestamp());
+        Crdt mergedCrdt = ((Crdt) previous.getPayload()).merge((Crdt) message.getPayload());
+        merged.setPayload(mergedCrdt);
+        boolean replaced = sharedData.replace(message.getKey(), previous, merged);
+        if (replaced){
+          return;
+        }
+      } else {
+        if (previous.getTimestamp() < message.getTimestamp()){
+          boolean result = sharedData.replace(message.getKey(), previous, message);
+          if (result){
+            return;
+          }
+        } else {
+          return;
+        }
+      }
+    }
+  }
+  
+  public void addPerNodeData(PerNodeDataMessage message){
+    ConcurrentHashMap<String,PerNodeDataMessage> nodeMap = new ConcurrentHashMap<>();
+    nodeMap.put(message.getKey(), message);
+    nodeMap = perNodeData.putIfAbsent(message.getNodeId(), nodeMap);
+    if (nodeMap != null){
+      PerNodeDataMessage current = nodeMap.get(message.getKey());
+      if (current == null){
+        nodeMap.putIfAbsent(message.getKey(), message);
+      } else {
+        if (current.getTimestamp() < message.getTimestamp()){
+          nodeMap.replace(message.getKey(), current, message);
+        }
+      }
+    }
+  }
+
+  public ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> getPerNodeData(){
+    return perNodeData;
+  }
+
+  public ConcurrentHashMap<String, SharedDataMessage> getSharedData() {
+    return sharedData;
+  }
+
+  public void shutdown(){
+    service.shutdown();
+    try {
+      service.awaitTermination(1, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      LOGGER.warn(e);
+    }
+    service.shutdownNow();
+  }
+
+  public void receive(Base base) {
+    if (!gossipManager.getMessageInvoker().invoke(this, gossipManager, base)) {
+      LOGGER.warn("received message can not be handled");
+    }
+  }
+
+  /**
+   * Sends a blocking message.
+   * @param message
+   * @param uri
+   * @throws RuntimeException if data can not be serialized or in transmission error
+   */
+  private void sendInternal(Base message, URI uri){
+    byte[] json_bytes;
+    try {
+      if (privKey == null){
+        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(message);
+      } else {
+        SignedPayload p = new SignedPayload();
+        p.setData(gossipManager.getObjectMapper().writeValueAsString(message).getBytes());
+        p.setSignature(sign(p.getData()));
+        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(p);
+      }
+    } catch (IOException e) {
+      messageSerdeException.mark();
+      throw new RuntimeException(e);
+    }
+    try (DatagramSocket socket = new DatagramSocket()) {
+      socket.setSoTimeout(gossipManager.getSettings().getGossipInterval() * 2);
+      InetAddress dest = InetAddress.getByName(uri.getHost());
+      DatagramPacket datagramPacket = new DatagramPacket(json_bytes, json_bytes.length, dest, uri.getPort());
+      socket.send(datagramPacket);
+      tranmissionSuccess.mark();
+    } catch (IOException e) {
+      tranmissionException.mark();
+      throw new RuntimeException(e);
+    }
+  }
+
+  public Response send(Base message, URI uri){
+    if (LOGGER.isDebugEnabled()){
+      LOGGER.debug("Sending " + message);
+      LOGGER.debug("Current request queue " + requests);
+    }
+
+    final Trackable t;
+    LatchAndBase latchAndBase = null;
+    if (message instanceof Trackable){
+      t = (Trackable) message;
+      latchAndBase = new LatchAndBase();
+      requests.put(t.getUuid() + "/" + t.getUriFrom(), latchAndBase);
+    } else {
+      t = null;
+    }
+    sendInternal(message, uri);
+    if (latchAndBase == null){
+      return null;
+    } 
+    
+    try {
+      boolean complete = latchAndBase.latch.await(1, TimeUnit.SECONDS);
+      if (complete){
+        return (Response) latchAndBase.base;
+      } else{
+        return null;
+      }
+    } catch (InterruptedException e) {
+      throw new RuntimeException(e);
+    } finally {
+      if (latchAndBase != null){
+        requests.remove(t.getUuid() + "/" + t.getUriFrom());
+      }
+    }
+  }
+
+  /**
+   * Sends a message across the network while blocking. Catches and ignores IOException in transmission. Used
+   * when the protocol for the message is not to wait for a response
+   * @param message the message to send
+   * @param u the uri to send it to
+   */
+  public void sendOneWay(Base message, URI u){
+    byte[] json_bytes;
+    try {
+      if (privKey == null){
+        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(message);
+      } else {
+        SignedPayload p = new SignedPayload();
+        p.setData(gossipManager.getObjectMapper().writeValueAsString(message).getBytes());
+        p.setSignature(sign(p.getData()));
+        json_bytes = gossipManager.getObjectMapper().writeValueAsBytes(p);
+      }
+    } catch (IOException e) {
+      messageSerdeException.mark();
+      throw new RuntimeException(e);
+    }
+    try (DatagramSocket socket = new DatagramSocket()) {
+      socket.setSoTimeout(gossipManager.getSettings().getGossipInterval() * 2);
+      InetAddress dest = InetAddress.getByName(u.getHost());
+      DatagramPacket datagramPacket = new DatagramPacket(json_bytes, json_bytes.length, dest, u.getPort());
+      socket.send(datagramPacket);
+      tranmissionSuccess.mark();
+    } catch (IOException ex) {
+      tranmissionException.mark();
+      LOGGER.debug("Send one way failed", ex);
+    }
+  }
+
+  public void handleResponse(String k, Base v) {
+    LatchAndBase latch = requests.get(k);
+    latch.base = v;
+    latch.latch.countDown();
+  }
+
+  /**
+   * Merge lists from remote members and update heartbeats
+   *
+   * @param gossipManager
+   * @param senderMember
+   * @param remoteList
+   *
+   */
+  public void mergeLists(GossipManager gossipManager, RemoteMember senderMember,
+          List<Member> remoteList) {
+    if (LOGGER.isDebugEnabled()){
+      debugState(senderMember, remoteList);
+    }
+    for (LocalMember i : gossipManager.getDeadMembers()) {
+      if (i.getId().equals(senderMember.getId())) {
+        LOGGER.debug(gossipManager.getMyself() + " contacted by dead member " + senderMember.getUri());
+        i.recordHeartbeat(senderMember.getHeartbeat());
+        i.setHeartbeat(senderMember.getHeartbeat());
+        //TODO consider forcing an UP here
+      }
+    }
+    for (Member remoteMember : remoteList) {
+      if (remoteMember.getId().equals(gossipManager.getMyself().getId())) {
+        continue;
+      }
+      LocalMember aNewMember = new LocalMember(remoteMember.getClusterName(),
+      remoteMember.getUri(),
+      remoteMember.getId(),
+      remoteMember.getHeartbeat(),
+      remoteMember.getProperties(),
+      gossipManager.getSettings().getWindowSize(),
+      gossipManager.getSettings().getMinimumSamples(),
+      gossipManager.getSettings().getDistribution());
+      aNewMember.recordHeartbeat(remoteMember.getHeartbeat());
+      Object result = gossipManager.getMembers().putIfAbsent(aNewMember, GossipState.UP);
+      if (result != null){
+        for (Entry<LocalMember, GossipState> localMember : gossipManager.getMembers().entrySet()){
+          if (localMember.getKey().getId().equals(remoteMember.getId())){
+            localMember.getKey().recordHeartbeat(remoteMember.getHeartbeat());
+            localMember.getKey().setHeartbeat(remoteMember.getHeartbeat());
+            localMember.getKey().setProperties(remoteMember.getProperties());
+          }
+        }
+      }
+    }
+    if (LOGGER.isDebugEnabled()){
+      debugState(senderMember, remoteList);
+    }
+  }
+
+  private void debugState(RemoteMember senderMember,
+          List<Member> remoteList){
+    LOGGER.warn(
+          "-----------------------\n" +
+          "Me " + gossipManager.getMyself() + "\n" +
+          "Sender " + senderMember + "\n" +
+          "RemoteList " + remoteList + "\n" +
+          "Live " + gossipManager.getLiveMembers()+ "\n" +
+          "Dead " + gossipManager.getDeadMembers()+ "\n" +
+          "=======================");
+  }
+
+  @SuppressWarnings("rawtypes")
+  public Crdt merge(SharedDataMessage message) {
+    for (;;){
+      SharedDataMessage previous = sharedData.putIfAbsent(message.getKey(), message);
+      if (previous == null){
+        return (Crdt) message.getPayload();
+      }
+      SharedDataMessage copy = new SharedDataMessage();
+      copy.setExpireAt(message.getExpireAt());
+      copy.setKey(message.getKey());
+      copy.setNodeId(message.getNodeId());
+      copy.setTimestamp(message.getTimestamp());
+      @SuppressWarnings("unchecked")
+      Crdt merged = ((Crdt) previous.getPayload()).merge((Crdt) message.getPayload());
+      copy.setPayload(merged);
+      boolean replaced = sharedData.replace(message.getKey(), previous, copy);
+      if (replaced){
+        return merged;
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java b/gossip-base/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java
new file mode 100644
index 0000000..6d3765a
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/GossipCoreConstants.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+public interface GossipCoreConstants {
+  String WORKQUEUE_SIZE = "gossip.core.workqueue.size";
+  String PER_NODE_DATA_SIZE = "gossip.core.pernodedata.size"; 
+  String SHARED_DATA_SIZE = "gossip.core.shareddata.size";
+  String REQUEST_SIZE = "gossip.core.requests.size";
+  String THREADPOOL_ACTIVE = "gossip.core.threadpool.active";
+  String THREADPOOL_SIZE = "gossip.core.threadpool.size";
+  String MESSAGE_SERDE_EXCEPTION = "gossip.core.message_serde_exception";
+  String MESSAGE_TRANSMISSION_EXCEPTION = "gossip.core.message_transmission_exception";
+  String MESSAGE_TRANSMISSION_SUCCESS = "gossip.core.message_transmission_success";
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/GossipManager.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/GossipManager.java b/gossip-base/src/main/java/org/apache/gossip/manager/GossipManager.java
new file mode 100644
index 0000000..c2b50ae
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/GossipManager.java
@@ -0,0 +1,319 @@
+/*
+ * 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 com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.LocalMember;
+import org.apache.gossip.Member;
+import org.apache.gossip.crdt.Crdt;
+import org.apache.gossip.event.GossipListener;
+import org.apache.gossip.event.GossipState;
+import org.apache.gossip.manager.handlers.MessageInvoker;
+import org.apache.gossip.manager.impl.OnlyProcessReceivedPassiveGossipThread;
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.SharedDataMessage;
+import org.apache.log4j.Logger;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+public abstract class GossipManager {
+
+  public static final Logger LOGGER = Logger.getLogger(GossipManager.class);
+
+  private final ConcurrentSkipListMap<LocalMember, GossipState> members;
+  private final LocalMember me;
+  private final GossipSettings settings;
+  private final AtomicBoolean gossipServiceRunning;
+  private AbstractActiveGossiper activeGossipThread;
+  private PassiveGossipThread passiveGossipThread;
+  private ExecutorService gossipThreadExecutor;
+  private final GossipCore gossipCore;
+  private final DataReaper dataReaper;
+  private final Clock clock;
+  private final ScheduledExecutorService scheduledServiced;
+  private final MetricRegistry registry;
+  private final RingStatePersister ringState;
+  private final UserDataPersister userDataState;
+  private final GossipMemberStateRefresher memberStateRefresher;
+  private final ObjectMapper objectMapper;
+
+  private final MessageInvoker messageInvoker;
+
+  public GossipManager(String cluster,
+                       URI uri, String id, Map<String, String> properties, GossipSettings settings,
+                       List<Member> gossipMembers, GossipListener listener, MetricRegistry registry,
+                       ObjectMapper objectMapper, MessageInvoker messageInvoker) {
+    this.settings = settings;
+    this.messageInvoker = messageInvoker;
+
+    clock = new SystemClock();
+    me = new LocalMember(cluster, uri, id, clock.nanoTime(), properties,
+            settings.getWindowSize(), settings.getMinimumSamples(), settings.getDistribution());
+    gossipCore = new GossipCore(this, registry);
+    dataReaper = new DataReaper(gossipCore, clock);
+    members = new ConcurrentSkipListMap<>();
+    for (Member startupMember : gossipMembers) {
+      if (!startupMember.equals(me)) {
+        LocalMember member = new LocalMember(startupMember.getClusterName(),
+                startupMember.getUri(), startupMember.getId(),
+                clock.nanoTime(), startupMember.getProperties(), settings.getWindowSize(),
+                settings.getMinimumSamples(), settings.getDistribution());
+        //TODO should members start in down state?
+        members.put(member, GossipState.DOWN);
+      }
+    }
+    gossipThreadExecutor = Executors.newCachedThreadPool();
+    gossipServiceRunning = new AtomicBoolean(true);
+    this.scheduledServiced = Executors.newScheduledThreadPool(1);
+    this.registry = registry;
+    this.ringState = new RingStatePersister(this);
+    this.userDataState = new UserDataPersister(this, this.gossipCore);
+    this.memberStateRefresher = new GossipMemberStateRefresher(members, settings, listener, this::findPerNodeGossipData);
+    this.objectMapper = objectMapper;
+    readSavedRingState();
+    readSavedDataState();
+  }
+
+  public MessageInvoker getMessageInvoker() {
+    return messageInvoker;
+  }
+
+  public ConcurrentSkipListMap<LocalMember, GossipState> getMembers() {
+    return members;
+  }
+
+  public GossipSettings getSettings() {
+    return settings;
+  }
+
+  /**
+   * @return a read only list of members found in the DOWN state.
+   */
+  public List<LocalMember> getDeadMembers() {
+    return Collections.unmodifiableList(
+            members.entrySet()
+                    .stream()
+                    .filter(entry -> GossipState.DOWN.equals(entry.getValue()))
+                    .map(Entry::getKey).collect(Collectors.toList()));
+  }
+
+  /**
+   *
+   * @return a read only list of members found in the UP state
+   */
+  public List<LocalMember> getLiveMembers() {
+    return Collections.unmodifiableList(
+            members.entrySet()
+                    .stream()
+                    .filter(entry -> GossipState.UP.equals(entry.getValue()))
+                    .map(Entry::getKey).collect(Collectors.toList()));
+  }
+
+  public LocalMember getMyself() {
+    return me;
+  }
+
+  private AbstractActiveGossiper constructActiveGossiper(){
+    try {
+      Constructor<?> c = Class.forName(settings.getActiveGossipClass()).getConstructor(GossipManager.class, GossipCore.class, MetricRegistry.class);
+      return (AbstractActiveGossiper) c.newInstance(this, gossipCore, registry);
+    } catch (NoSuchMethodException | SecurityException | ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Starts the client. Specifically, start the various cycles for this protocol. Start the gossip
+   * thread and start the receiver thread.
+   */
+  public void init() {
+    passiveGossipThread = new OnlyProcessReceivedPassiveGossipThread(this, gossipCore);
+    gossipThreadExecutor.execute(passiveGossipThread);
+    activeGossipThread = constructActiveGossiper();
+    activeGossipThread.init();
+    dataReaper.init();
+    scheduledServiced.scheduleAtFixedRate(ringState, 60, 60, TimeUnit.SECONDS);
+    scheduledServiced.scheduleAtFixedRate(userDataState, 60, 60, TimeUnit.SECONDS);
+    scheduledServiced.scheduleAtFixedRate(memberStateRefresher, 0, 100, TimeUnit.MILLISECONDS);
+    LOGGER.debug("The GossipManager is started.");
+  }
+
+  private void readSavedRingState() {
+    for (LocalMember l : ringState.readFromDisk()){
+      LocalMember member = new LocalMember(l.getClusterName(),
+              l.getUri(), l.getId(),
+              clock.nanoTime(), l.getProperties(), settings.getWindowSize(),
+              settings.getMinimumSamples(), settings.getDistribution());
+      members.putIfAbsent(member, GossipState.DOWN);
+    }
+  }
+
+  private void readSavedDataState() {
+    for (Entry<String, ConcurrentHashMap<String, PerNodeDataMessage>> l : userDataState.readPerNodeFromDisk().entrySet()){
+      for (Entry<String, PerNodeDataMessage> j : l.getValue().entrySet()){
+        gossipCore.addPerNodeData(j.getValue());
+      }
+    }
+    for (Entry<String, SharedDataMessage> l: userDataState.readSharedDataFromDisk().entrySet()){
+      gossipCore.addSharedData(l.getValue());
+    }
+  }
+
+  /**
+   * Shutdown the gossip service.
+   */
+  public void shutdown() {
+    gossipServiceRunning.set(false);
+    gossipThreadExecutor.shutdown();
+    gossipCore.shutdown();
+    dataReaper.close();
+    if (passiveGossipThread != null) {
+      passiveGossipThread.shutdown();
+    }
+    if (activeGossipThread != null) {
+      activeGossipThread.shutdown();
+    }
+    try {
+      boolean result = gossipThreadExecutor.awaitTermination(10, TimeUnit.MILLISECONDS);
+      if (!result) {
+        LOGGER.error("executor shutdown timed out");
+      }
+    } catch (InterruptedException e) {
+      LOGGER.error(e);
+    }
+    gossipThreadExecutor.shutdownNow();
+    scheduledServiced.shutdown();
+    try {
+      scheduledServiced.awaitTermination(1, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      LOGGER.error(e);
+    }
+    scheduledServiced.shutdownNow();
+  }
+
+  public void gossipPerNodeData(PerNodeDataMessage message){
+    Objects.nonNull(message.getKey());
+    Objects.nonNull(message.getTimestamp());
+    Objects.nonNull(message.getPayload());
+    message.setNodeId(me.getId());
+    gossipCore.addPerNodeData(message);
+  }
+
+  public void gossipSharedData(SharedDataMessage message){
+    Objects.nonNull(message.getKey());
+    Objects.nonNull(message.getTimestamp());
+    Objects.nonNull(message.getPayload());
+    message.setNodeId(me.getId());
+    gossipCore.addSharedData(message);
+  }
+
+
+  @SuppressWarnings("rawtypes")
+  public Crdt findCrdt(String key){
+    SharedDataMessage l = gossipCore.getSharedData().get(key);
+    if (l == null){
+      return null;
+    }
+    if (l.getExpireAt() < clock.currentTimeMillis()){
+      return null;
+    } else {
+      return (Crdt) l.getPayload();
+    }
+  }
+
+  @SuppressWarnings("rawtypes")
+  public Crdt merge(SharedDataMessage message){
+    Objects.nonNull(message.getKey());
+    Objects.nonNull(message.getTimestamp());
+    Objects.nonNull(message.getPayload());
+    message.setNodeId(me.getId());
+    if (! (message.getPayload() instanceof Crdt)){
+      throw new IllegalArgumentException("Not a subclass of CRDT " + message.getPayload());
+    }
+    return gossipCore.merge(message);
+  }
+
+  public PerNodeDataMessage findPerNodeGossipData(String nodeId, String key){
+    ConcurrentHashMap<String, PerNodeDataMessage> j = gossipCore.getPerNodeData().get(nodeId);
+    if (j == null){
+      return null;
+    } else {
+      PerNodeDataMessage l = j.get(key);
+      if (l == null){
+        return null;
+      }
+      if (l.getExpireAt() != null && l.getExpireAt() < clock.currentTimeMillis()) {
+        return null;
+      }
+      return l;
+    }
+  }
+
+  public SharedDataMessage findSharedGossipData(String key){
+    SharedDataMessage l = gossipCore.getSharedData().get(key);
+    if (l == null){
+      return null;
+    }
+    if (l.getExpireAt() < clock.currentTimeMillis()){
+      return null;
+    } else {
+      return l;
+    }
+  }
+
+  public DataReaper getDataReaper() {
+    return dataReaper;
+  }
+
+  public RingStatePersister getRingState() {
+    return ringState;
+  }
+
+  public UserDataPersister getUserDataState() {
+    return userDataState;
+  }
+
+  public GossipMemberStateRefresher getMemberStateRefresher() {
+    return memberStateRefresher;
+  }
+
+  public Clock getClock() {
+    return clock;
+  }
+
+  public ObjectMapper getObjectMapper() {
+    return objectMapper;
+  }
+
+  public MetricRegistry getRegistry() {
+    return registry;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java b/gossip-base/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java
new file mode 100644
index 0000000..b87045b
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/GossipManagerBuilder.java
@@ -0,0 +1,152 @@
+/*
+ * 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 com.fasterxml.jackson.core.JsonGenerator.Feature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.gossip.Member;
+import org.apache.gossip.GossipSettings;
+import org.apache.gossip.StartupSettings;
+import org.apache.gossip.crdt.CrdtModule;
+import org.apache.gossip.event.GossipListener;
+import org.apache.gossip.manager.handlers.DefaultMessageInvoker;
+import org.apache.gossip.manager.handlers.MessageInvoker;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class GossipManagerBuilder {
+
+  public static ManagerBuilder newBuilder() {
+    return new ManagerBuilder();
+  }
+
+  public static final class ManagerBuilder {
+    private String cluster;
+    private URI uri;
+    private String id;
+    private GossipSettings settings;
+    private List<Member> gossipMembers;
+    private GossipListener listener;
+    private MetricRegistry registry;
+    private Map<String,String> properties;
+    private ObjectMapper objectMapper;
+    private MessageInvoker messageInvoker;
+
+    private ManagerBuilder() {}
+
+    private void checkArgument(boolean check, String msg) {
+      if (!check) {
+        throw new IllegalArgumentException(msg);
+      }
+    }
+
+    public ManagerBuilder cluster(String cluster) {
+      this.cluster = cluster;
+      return this;
+    }
+    
+    public ManagerBuilder properties(Map<String,String> properties) {
+      this.properties = properties;
+      return this;
+    }
+
+    public ManagerBuilder id(String id) {
+      this.id = id;
+      return this;
+    }
+
+    public ManagerBuilder gossipSettings(GossipSettings settings) {
+      this.settings = settings;
+      return this;
+    }
+    
+    public ManagerBuilder startupSettings(StartupSettings startupSettings) {
+      this.cluster = startupSettings.getCluster();
+      this.id = startupSettings.getId();
+      this.settings = startupSettings.getGossipSettings();
+      this.gossipMembers = startupSettings.getGossipMembers();
+      this.uri = startupSettings.getUri();
+      return this;
+    }
+
+    public ManagerBuilder gossipMembers(List<Member> members) {
+      this.gossipMembers = members;
+      return this;
+    }
+
+    public ManagerBuilder listener(GossipListener listener) {
+      this.listener = listener;
+      return this;
+    }
+    
+    public ManagerBuilder registry(MetricRegistry registry) {
+      this.registry = registry;
+      return this;
+    }
+
+    public ManagerBuilder uri(URI uri){
+      this.uri = uri;
+      return this;
+    }
+    
+    public ManagerBuilder mapper(ObjectMapper objectMapper){
+      this.objectMapper = objectMapper;
+      return this;
+    }
+
+    public ManagerBuilder messageInvoker(MessageInvoker messageInvoker) {
+      this.messageInvoker = messageInvoker;
+      return this;
+    }
+
+    public GossipManager build() {
+      checkArgument(id != null, "You must specify an id");
+      checkArgument(cluster != null, "You must specify a cluster name");
+      checkArgument(settings != null, "You must specify gossip settings");
+      checkArgument(uri != null, "You must specify a uri");
+      if (registry == null){
+        registry = new MetricRegistry();
+      }
+      if (properties == null){
+        properties = new HashMap<String,String>();
+      }
+      if (listener == null){
+        listener((a,b) -> {});
+      }
+      if (gossipMembers == null) {
+        gossipMembers = new ArrayList<>();
+      }
+      if (objectMapper == null) {
+        objectMapper = new ObjectMapper();
+        objectMapper.enableDefaultTyping();
+        objectMapper.registerModule(new CrdtModule());
+        objectMapper.configure(Feature.WRITE_NUMBERS_AS_STRINGS, false);
+      }
+      if (messageInvoker == null) {
+        messageInvoker = new DefaultMessageInvoker();
+      } 
+      return new GossipManager(cluster, uri, id, properties, settings, gossipMembers, listener, registry, objectMapper, messageInvoker) {} ;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.java b/gossip-base/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.java
new file mode 100644
index 0000000..1836309
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/GossipMemberStateRefresher.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 org.apache.gossip.GossipSettings;
+import org.apache.gossip.LocalMember;
+import org.apache.gossip.event.GossipListener;
+import org.apache.gossip.event.GossipState;
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.ShutdownMessage;
+import org.apache.log4j.Logger;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+
+public class GossipMemberStateRefresher implements Runnable {
+  public static final Logger LOGGER = Logger.getLogger(GossipMemberStateRefresher.class);
+
+  private final Map<LocalMember, GossipState> members;
+  private final GossipSettings settings;
+  private final GossipListener listener;
+  private final Clock clock;
+  private final BiFunction<String, String, PerNodeDataMessage> findPerNodeGossipData;
+
+  public GossipMemberStateRefresher(Map<LocalMember, GossipState> members, GossipSettings settings,
+                                    GossipListener listener, BiFunction<String, String, PerNodeDataMessage> findPerNodeGossipData) {
+    this.members = members;
+    this.settings = settings;
+    this.listener = listener;
+    this.findPerNodeGossipData = findPerNodeGossipData;
+    clock = new SystemClock();
+  }
+
+  public void run() {
+    try {
+      runOnce();
+    } catch (RuntimeException ex) {
+      LOGGER.warn("scheduled state had exception", ex);
+    }
+  }
+
+  public void runOnce() {
+    for (Entry<LocalMember, GossipState> entry : members.entrySet()) {
+      boolean userDown = processOptimisticShutdown(entry);
+      if (userDown)
+        continue;
+
+      Double phiMeasure = entry.getKey().detect(clock.nanoTime());
+      GossipState requiredState;
+
+      if (phiMeasure != null) {
+        requiredState = calcRequiredState(phiMeasure);
+      } else {
+        requiredState = calcRequiredStateCleanupInterval(entry.getKey(), entry.getValue());
+      }
+
+      if (entry.getValue() != requiredState) {
+        members.put(entry.getKey(), requiredState);
+        listener.gossipEvent(entry.getKey(), requiredState);
+      }
+    }
+  }
+
+  public GossipState calcRequiredState(Double phiMeasure) {
+    if (phiMeasure > settings.getConvictThreshold())
+      return GossipState.DOWN;
+    else
+      return GossipState.UP;
+  }
+
+  public GossipState calcRequiredStateCleanupInterval(LocalMember member, GossipState state) {
+    long now = clock.nanoTime();
+    long nowInMillis = TimeUnit.MILLISECONDS.convert(now, TimeUnit.NANOSECONDS);
+    if (nowInMillis - settings.getCleanupInterval() > member.getHeartbeat()) {
+      return GossipState.DOWN;
+    } else {
+      return state;
+    }
+  }
+
+  /**
+   * If we have a special key the per-node data that means that the node has sent us
+   * a pre-emptive shutdown message. We process this so node is seen down sooner
+   *
+   * @param l member to consider
+   * @return true if node forced down
+   */
+  public boolean processOptimisticShutdown(Entry<LocalMember, GossipState> l) {
+    PerNodeDataMessage m = findPerNodeGossipData.apply(l.getKey().getId(), ShutdownMessage.PER_NODE_KEY);
+    if (m == null) {
+      return false;
+    }
+    ShutdownMessage s = (ShutdownMessage) m.getPayload();
+    if (s.getShutdownAtNanos() > l.getKey().getHeartbeat()) {
+      members.put(l.getKey(), GossipState.DOWN);
+      if (l.getValue() == GossipState.UP) {
+        listener.gossipEvent(l.getKey(), GossipState.DOWN);
+      }
+      return true;
+    }
+    return false;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java b/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java
new file mode 100644
index 0000000..3bcc344
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipConstants.java
@@ -0,0 +1,23 @@
+/*
+ * 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;
+
+public interface PassiveGossipConstants {
+  String SIGNED_MESSAGE = "gossip.passive.signed_message";
+  String UNSIGNED_MESSAGE = "gossip.passive.unsigned_message";
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipThread.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipThread.java b/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipThread.java
new file mode 100644
index 0000000..ae28bf7
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/PassiveGossipThread.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.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.gossip.model.Base;
+import org.apache.gossip.model.SignedPayload;
+import org.apache.log4j.Logger;
+
+import com.codahale.metrics.Meter;
+
+/**
+ * This class handles the passive cycle,
+ * where this client has received an incoming message. 
+ */
+abstract public class PassiveGossipThread implements Runnable {
+
+  public static final Logger LOGGER = Logger.getLogger(PassiveGossipThread.class);
+
+  /** The socket used for the passive thread of the gossip service. */
+  private final DatagramSocket server;
+  private final AtomicBoolean keepRunning;
+  private final GossipCore gossipCore;
+  private final GossipManager gossipManager;
+  private final Meter signed;
+  private final Meter unsigned;
+
+  public PassiveGossipThread(GossipManager gossipManager, GossipCore gossipCore) {
+    this.gossipManager = gossipManager;
+    this.gossipCore = gossipCore;
+    if (gossipManager.getMyself().getClusterName() == null){
+      throw new IllegalArgumentException("Cluster was null");
+    }
+    try {
+      SocketAddress socketAddress = new InetSocketAddress(gossipManager.getMyself().getUri().getHost(),
+              gossipManager.getMyself().getUri().getPort());
+      server = new DatagramSocket(socketAddress);
+    } catch (SocketException ex) {
+      LOGGER.warn(ex);
+      throw new RuntimeException(ex);
+    }
+    keepRunning = new AtomicBoolean(true);
+    signed = gossipManager.getRegistry().meter(PassiveGossipConstants.SIGNED_MESSAGE);
+    unsigned = gossipManager.getRegistry().meter(PassiveGossipConstants.UNSIGNED_MESSAGE);
+  }
+
+  @Override
+  public void run() {
+    while (keepRunning.get()) {
+      try {
+        byte[] buf = new byte[server.getReceiveBufferSize()];
+        DatagramPacket p = new DatagramPacket(buf, buf.length);
+        server.receive(p);
+        debug(p.getData());
+        try {
+          Base activeGossipMessage = gossipManager.getObjectMapper().readValue(p.getData(), Base.class);
+          if (activeGossipMessage instanceof SignedPayload){
+            SignedPayload s = (SignedPayload) activeGossipMessage;
+            Base nested = gossipManager.getObjectMapper().readValue(s.getData(), Base.class);
+            gossipCore.receive(nested);
+            signed.mark();
+          } else {
+            gossipCore.receive(activeGossipMessage);
+            unsigned.mark();
+          }
+          gossipManager.getMemberStateRefresher().run();
+        } catch (RuntimeException ex) {//TODO trap json exception
+          LOGGER.error("Unable to process message", ex);
+        }
+      } catch (IOException e) {
+        LOGGER.error(e);
+        keepRunning.set(false);
+      }
+    }
+    shutdown();
+  }
+
+  private void debug(byte[] jsonBytes) {
+    if (LOGGER.isDebugEnabled()){
+      String receivedMessage = new String(jsonBytes);
+      LOGGER.debug("Received message ( bytes): " + receivedMessage);
+    }
+  }
+
+  public void shutdown() {
+    try {
+      server.close();
+    } catch (RuntimeException ex) {
+    }
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/RingStatePersister.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/RingStatePersister.java b/gossip-base/src/main/java/org/apache/gossip/manager/RingStatePersister.java
new file mode 100644
index 0000000..7e42562
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/RingStatePersister.java
@@ -0,0 +1,76 @@
+/*
+ * 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.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.NavigableSet;
+
+import org.apache.gossip.LocalMember;
+import org.apache.log4j.Logger;
+
+public class RingStatePersister implements Runnable {
+
+  private static final Logger LOGGER = Logger.getLogger(RingStatePersister.class);
+  private GossipManager parent;
+  
+  public RingStatePersister(GossipManager parent){
+    this.parent = parent;
+  }
+  
+  @Override
+  public void run() {
+    writeToDisk();
+  }
+  
+  File computeTarget(){
+    return new File(parent.getSettings().getPathToRingState(), "ringstate." + parent.getMyself().getClusterName() + "." 
+            + parent.getMyself().getId() + ".json");
+  }
+  
+  void writeToDisk(){
+    if (!parent.getSettings().isPersistRingState()){
+      return;
+    }
+    NavigableSet<LocalMember> i = parent.getMembers().keySet();
+    try (FileOutputStream fos = new FileOutputStream(computeTarget())){
+      parent.getObjectMapper().writeValue(fos, i);
+    } catch (IOException e) {
+      LOGGER.debug(e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  List<LocalMember> readFromDisk(){
+    if (!parent.getSettings().isPersistRingState()){
+      return Collections.emptyList();
+    }
+    try (FileInputStream fos = new FileInputStream(computeTarget())){
+      return parent.getObjectMapper().readValue(fos, ArrayList.class);
+    } catch (IOException e) {
+      LOGGER.debug(e);
+    }
+    return Collections.emptyList();
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java b/gossip-base/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java
new file mode 100644
index 0000000..e47fe2a
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/SimpleActiveGossipper.java
@@ -0,0 +1,110 @@
+/*
+ * 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.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.gossip.LocalMember;
+
+import com.codahale.metrics.MetricRegistry;
+
+/**
+ * Base implementation gossips randomly to live nodes periodically gossips to dead ones
+ *
+ */
+public class SimpleActiveGossipper extends AbstractActiveGossiper {
+
+  private ScheduledExecutorService scheduledExecutorService;
+  private final BlockingQueue<Runnable> workQueue;
+  private ThreadPoolExecutor threadService;
+  
+  public SimpleActiveGossipper(GossipManager gossipManager, GossipCore gossipCore,
+          MetricRegistry registry) {
+    super(gossipManager, gossipCore, registry);
+    scheduledExecutorService = Executors.newScheduledThreadPool(2);
+    workQueue = new ArrayBlockingQueue<Runnable>(1024);
+    threadService = new ThreadPoolExecutor(1, 30, 1, TimeUnit.SECONDS, workQueue,
+            new ThreadPoolExecutor.DiscardOldestPolicy());
+  }
+
+  @Override
+  public void init() {
+    super.init();
+    scheduledExecutorService.scheduleAtFixedRate(() -> {
+      threadService.execute(() -> {
+        sendToALiveMember();
+      });
+    }, 0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
+    scheduledExecutorService.scheduleAtFixedRate(() -> {
+      sendToDeadMember();
+    }, 0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
+    scheduledExecutorService.scheduleAtFixedRate(
+            () -> sendPerNodeData(gossipManager.getMyself(),
+                    selectPartner(gossipManager.getLiveMembers())),
+            0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
+    scheduledExecutorService.scheduleAtFixedRate(
+            () -> sendSharedData(gossipManager.getMyself(),
+                    selectPartner(gossipManager.getLiveMembers())),
+            0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
+  }
+  
+  @Override
+  public void shutdown() {
+    super.shutdown();
+    scheduledExecutorService.shutdown();
+    try {
+      scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      LOGGER.debug("Issue during shutdown", e);
+    }
+    sendShutdownMessage();
+    threadService.shutdown();
+    try {
+      threadService.awaitTermination(5, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      LOGGER.debug("Issue during shutdown", e);
+    }
+  }
+
+  protected void sendToALiveMember(){
+    LocalMember member = selectPartner(gossipManager.getLiveMembers());
+    sendMembershipList(gossipManager.getMyself(), member);
+  }
+  
+  protected void sendToDeadMember(){
+    LocalMember member = selectPartner(gossipManager.getDeadMembers());
+    sendMembershipList(gossipManager.getMyself(), member);
+  }
+  
+  /**
+   * sends an optimistic shutdown message to several clusters nodes
+   */
+  protected void sendShutdownMessage(){
+    List<LocalMember> l = gossipManager.getLiveMembers();
+    int sendTo = l.size() < 3 ? 1 : l.size() / 2;
+    for (int i = 0; i < sendTo; i++) {
+      threadService.execute(() -> sendShutdownMessage(gossipManager.getMyself(), selectPartner(l)));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/SystemClock.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/SystemClock.java b/gossip-base/src/main/java/org/apache/gossip/manager/SystemClock.java
new file mode 100644
index 0000000..04a7080
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/SystemClock.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+public class SystemClock implements Clock {
+
+  @Override
+  public long currentTimeMillis() {
+    return System.currentTimeMillis();
+  }
+
+  @Override
+  public long nanoTime() {
+    return System.nanoTime();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/UserDataPersister.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/UserDataPersister.java b/gossip-base/src/main/java/org/apache/gossip/manager/UserDataPersister.java
new file mode 100644
index 0000000..3b9eafa
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/UserDataPersister.java
@@ -0,0 +1,107 @@
+/*
+ * 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.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.gossip.model.PerNodeDataMessage;
+import org.apache.gossip.model.SharedDataMessage;
+import org.apache.log4j.Logger;
+
+public class UserDataPersister implements Runnable {
+  
+  private static final Logger LOGGER = Logger.getLogger(UserDataPersister.class);
+  private final GossipManager parent;
+  private final GossipCore gossipCore; 
+  
+  UserDataPersister(GossipManager parent, GossipCore gossipCore){
+    this.parent = parent;
+    this.gossipCore = gossipCore;
+  }
+  
+  File computeSharedTarget(){
+    return new File(parent.getSettings().getPathToDataState(), "shareddata."
+            + parent.getMyself().getClusterName() + "." + parent.getMyself().getId() + ".json");
+  }
+  
+  File computePerNodeTarget() {
+    return new File(parent.getSettings().getPathToDataState(), "pernodedata."
+            + parent.getMyself().getClusterName() + "." + parent.getMyself().getId() + ".json");
+  }
+  
+  @SuppressWarnings("unchecked")
+  ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> readPerNodeFromDisk(){
+    if (!parent.getSettings().isPersistDataState()){
+      return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
+    }
+    try (FileInputStream fos = new FileInputStream(computePerNodeTarget())){
+      return parent.getObjectMapper().readValue(fos, ConcurrentHashMap.class);
+    } catch (IOException e) {
+      LOGGER.debug(e);
+    }
+    return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
+  }
+  
+  void writePerNodeToDisk(){
+    if (!parent.getSettings().isPersistDataState()){
+      return;
+    }
+    try (FileOutputStream fos = new FileOutputStream(computePerNodeTarget())){
+      parent.getObjectMapper().writeValue(fos, gossipCore.getPerNodeData());
+    } catch (IOException e) {
+      LOGGER.warn(e);
+    }
+  }
+  
+  void writeSharedToDisk(){
+    if (!parent.getSettings().isPersistDataState()){
+      return;
+    }
+    try (FileOutputStream fos = new FileOutputStream(computeSharedTarget())){
+      parent.getObjectMapper().writeValue(fos, gossipCore.getSharedData());
+    } catch (IOException e) {
+      LOGGER.warn(e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  ConcurrentHashMap<String, SharedDataMessage> readSharedDataFromDisk(){
+    if (!parent.getSettings().isPersistRingState()){
+      return new ConcurrentHashMap<String, SharedDataMessage>();
+    }
+    try (FileInputStream fos = new FileInputStream(computeSharedTarget())){
+      return parent.getObjectMapper().readValue(fos, ConcurrentHashMap.class);
+    } catch (IOException e) {
+      LOGGER.debug(e);
+    }
+    return new ConcurrentHashMap<String, SharedDataMessage>();
+  }
+  
+  /**
+   * Writes all pernode and shared data to disk 
+   */
+  @Override
+  public void run() {
+    writePerNodeToDisk();
+    writeSharedToDisk();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java
new file mode 100644
index 0000000..f5e568e
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/ActiveGossipMessageHandler.java
@@ -0,0 +1,74 @@
+/*
+ * 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.Member;
+import org.apache.gossip.RemoteMember;
+import org.apache.gossip.manager.GossipCore;
+import org.apache.gossip.manager.GossipManager;
+import org.apache.gossip.model.Base;
+import org.apache.gossip.udp.UdpActiveGossipMessage;
+import org.apache.gossip.udp.UdpActiveGossipOk;
+import org.apache.gossip.udp.UdpNotAMemberFault;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ActiveGossipMessageHandler implements MessageHandler {
+  @Override
+  public void invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    List<Member> remoteGossipMembers = new ArrayList<>();
+    RemoteMember senderMember = null;
+    UdpActiveGossipMessage activeGossipMessage = (UdpActiveGossipMessage) base;
+    for (int i = 0; i < activeGossipMessage.getMembers().size(); i++) {
+      URI u;
+      try {
+        u = new URI(activeGossipMessage.getMembers().get(i).getUri());
+      } catch (URISyntaxException e) {
+        GossipCore.LOGGER.debug("Gossip message with faulty URI", e);
+        continue;
+      }
+      RemoteMember member = new RemoteMember(
+              activeGossipMessage.getMembers().get(i).getCluster(),
+              u,
+              activeGossipMessage.getMembers().get(i).getId(),
+              activeGossipMessage.getMembers().get(i).getHeartbeat(),
+              activeGossipMessage.getMembers().get(i).getProperties());
+      if (i == 0) {
+        senderMember = member;
+      }
+      if (!(member.getClusterName().equals(gossipManager.getMyself().getClusterName()))) {
+        UdpNotAMemberFault f = new UdpNotAMemberFault();
+        f.setException("Not a member of this cluster " + i);
+        f.setUriFrom(activeGossipMessage.getUriFrom());
+        f.setUuid(activeGossipMessage.getUuid());
+        GossipCore.LOGGER.warn(f);
+        gossipCore.sendOneWay(f, member.getUri());
+        continue;
+      }
+      remoteGossipMembers.add(member);
+    }
+    UdpActiveGossipOk o = new UdpActiveGossipOk();
+    o.setUriFrom(activeGossipMessage.getUriFrom());
+    o.setUuid(activeGossipMessage.getUuid());
+    gossipCore.sendOneWay(o, senderMember.getUri());
+    gossipCore.mergeLists(gossipManager, senderMember, remoteGossipMembers);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/298b1ae3/gossip-base/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java
----------------------------------------------------------------------
diff --git a/gossip-base/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java
new file mode 100644
index 0000000..5b78ce3
--- /dev/null
+++ b/gossip-base/src/main/java/org/apache/gossip/manager/handlers/DefaultMessageInvoker.java
@@ -0,0 +1,40 @@
+/*
+ * 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.*;
+
+public class DefaultMessageInvoker implements MessageInvoker {
+  private final MessageInvokerCombiner mic;
+
+  public DefaultMessageInvoker() {
+    mic = new MessageInvokerCombiner();
+    mic.add(new SimpleMessageInvoker(Response.class, new ResponseHandler()));
+    mic.add(new SimpleMessageInvoker(ShutdownMessage.class, new ShutdownMessageHandler()));
+    mic.add(new SimpleMessageInvoker(PerNodeDataMessage.class, new PerNodeDataMessageHandler()));
+    mic.add(new SimpleMessageInvoker(SharedDataMessage.class, new SharedDataMessageHandler()));
+    mic.add(new SimpleMessageInvoker(ActiveGossipMessage.class, new ActiveGossipMessageHandler()));
+  }
+
+  public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
+    return mic.invoke(gossipCore, gossipManager, base);
+  }
+}