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);
+ }
+}