gossip-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ecapri...@apache.org
Subject incubator-gossip git commit: GOSSIP-86 Examples in separate module - Added Readme.
Date Thu, 08 Jun 2017 21:12:49 GMT
Repository: incubator-gossip
Updated Branches:
  refs/heads/master c62ebaf9b -> 9c9d96e56


GOSSIP-86 Examples in separate module - Added Readme.


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

Branch: refs/heads/master
Commit: 9c9d96e564eca1513a9776b9eba24d52787500d2
Parents: c62ebaf
Author: Terry Weymouth <weymouth@umich.edu>
Authored: Mon May 29 09:16:32 2017 -0400
Committer: Terry Weymouth <weymouth@umich.edu>
Committed: Mon Jun 5 08:21:46 2017 -0400

----------------------------------------------------------------------
 README.md                                       |   4 +
 .../examples/StandAloneDatacenterAndRack.java   |  62 -----
 .../apache/gossip/examples/StandAloneNode.java  |  47 ----
 .../examples/StandAloneNodeCrdtOrSet.java       | 115 ---------
 gossip-examples/.gitignore                      |   2 +
 gossip-examples/README.md                       | 246 +++++++++++++++++++
 gossip-examples/pom.xml                         |  45 ++++
 .../apache/gossip/examples/ExampleCommon.java   |  50 ++++
 .../examples/StandAloneDatacenterAndRack.java   |  67 +++++
 .../apache/gossip/examples/StandAloneNode.java  |  53 ++++
 .../examples/StandAloneNodeCrdtOrSet.java       | 122 +++++++++
 gossip-itest/.gitignore                         |   5 +
 pom.xml                                         |   5 +-
 13 files changed, 598 insertions(+), 225 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/9c9d96e5/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 86f179a..2eae09d 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,10 @@ Gossip protocol is a method for a group of nodes to discover and check the
livel
 
 The original implementation was forked from https://code.google.com/p/java-gossip/. Several
bug fixes and changes have already been added.
 
+A set of easily-run examples, illustrating various features of Gossip, are available in the
gossip-examples module. The README.md file, in that module described how to run those examples.
+
+Below, a list of code snippits which show how to incorproate Apache Gossip into your project.
 
+
 Usage
 -----
 

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/9c9d96e5/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
deleted file mode 100644
index 497894c..0000000
--- a/gossip-base/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/9c9d96e5/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
deleted file mode 100644
index 93421b1..0000000
--- a/gossip-base/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/9c9d96e5/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
deleted file mode 100644
index d78cf5e..0000000
--- a/gossip-base/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/9c9d96e5/gossip-examples/.gitignore
----------------------------------------------------------------------
diff --git a/gossip-examples/.gitignore b/gossip-examples/.gitignore
new file mode 100644
index 0000000..342545a
--- /dev/null
+++ b/gossip-examples/.gitignore
@@ -0,0 +1,2 @@
+# Generated by running examples
+*.mycluster.*.json

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/9c9d96e5/gossip-examples/README.md
----------------------------------------------------------------------
diff --git a/gossip-examples/README.md b/gossip-examples/README.md
new file mode 100644
index 0000000..aae7b88
--- /dev/null
+++ b/gossip-examples/README.md
@@ -0,0 +1,246 @@
+Running the Examples
+===================================================
+
+Apache Gossip is designed to run as library used by others. That is, it in intended as a
feature to be embedded in other code.
+
+These examples illustrate some simple cases of the invocation of Gossip from an "thin" application
layer, to illustrate various 
+features of the library. 
+
+For additional information see:
+* This [YouTube video](https://www.youtube.com/watch?v=bZXZrp7yBkw&t=39s) illustrating
and illuminating the first example.
+* This [YouTube video](https://www.youtube.com/watch?v=SqkJs0QDRdk) illustrating and illuminating
the second example.
+* A [general description of the Gossip Protocol](https://en.wikipedia.org/wiki/Gossip_protocol)
+
+Initial setup - Preconditions
+-----------------------------
+These instructions assume that you are using a Unix-like command line interface; translate
as necessary.
+
+Prior to running these examples you will need to have your environment set up to run java
and Maven
+commands: 
+* install java 8 - [https://java.com/](https://java.com/), and
+* install Maven - [https://maven.apache.org/install.html](https://maven.apache.org/install.html)
+
+Then, you will need a local copy of the code. The simplest is to download the project to
a local folder:
+* browse to [https://github.com/apache/incubator-gossip](https://github.com/apache/incubator-gossip)
+* click on the "Clone of Download" button
+* click on the "Download ZIP" option
+* unzip the file to in a convenient location
+In what follows, we will call the resulting project folder **incubator-gossip**.
+
+As an alternative, you can also [clone](https://help.github.com/articles/cloning-a-repository/)
+the GitHub repository.
+
+Lastly, you will need to use Maven to build and install the necessary dependencies:
+```
+cd incubator-gossip
+mvn install -DskipTests
+```
+
+When all that is finished are you ready to start running the first example...
+
+
+Running org.apache.gossip.examples.StandAloneNode
+-------------------------------------------------
+This first example illustrates the basic, underlying, communication layer the sets up and
maintains a gossip network cluster.
+
+In the [YouTube video](https://www.youtube.com/watch?v=bZXZrp7yBkw&t=39s) there is a
description of
+the architecture and a demonstration of running of this example. While the video was created
with an earlier version of the system,
+these instructions will get you going on that example.
+
+To run this example from the code (in a clone or download of the archive) simply change your
working directory
+to the gossip-examples module and run the application in maven.
+
+Specifically, after cloning or downloading the repository:
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneNode -Dexec.args="udp://localhost:10000
0 udp://localhost:10000 0"
+```
+
+This sets up a single StandAloneNode that starts out listening to itself. The arguments are:
+1. The URI (host and port) for the node - **udp://localhost:10000**
+2. The id for the node - **0**
+3. The URI for a "seed" node - **udp://localhost:10000**
+4. The id for that seed node - **0**
+
+Note. To stop the the example, simply kill the process (control-C, for example).
+
+In this application, the output uses a "terminal escape sequence" that clears the 
+terminal display and resets the cursor to the upper left corner.
+if, for some reason, this is not working in your case, you can add the (optional) flag '-s'
to the args in the 
+command line, to suppress this "clear screen" behavior. That is:
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneNode -Dexec.args="-s
udp://localhost:10000 0 udp://localhost:10000 0"
+```
+
+Normally, you would set up nodes in a network on separate hosts, but in this case, illustrating
the basic communications in gossip,
+we are just running all the nodes on the same host, localhost. The seed node will generally
be one of the other nodes in the
+network: enough information for this node to (eventually) acquire the list of all nodes in
its cluster.
+
+You will see that this gossip node prints out two list of know other nodes, live and dead.
The live nodes are nodes assumed to be active and
+connected, the dead nodes are nodes that have "gone missing" long enough to be assumed dormant
or disconnected. See details in the video.
+
+With only a single node running in this cluster, there are no other nodes detected, so both
the live and dead lists are empty.
+
+Then, in a separate terminal window, cd to the same folder and enter the the same run command
with the first two arguments 
+changed to reflect the fact that this is a different node
+1. host/port for the node - **udp://localhost:10001**
+2. id for the node - **1**
+
+That is:
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneNode -Dexec.args="udp://localhost:10001
1 udp://localhost:10000 0"
+```
+
+Now, because the "seed node" is the first node that we started, this second node is listening
to the first node, 
+and they exchange list of known nodes. And start listening to each other, so that in short
order they both have a list of live notes
+with one member, the other live node in the cluster.
+
+Finally, in yet another terminal window, cd to the same folder and enter the the same run
command with the first two arguments changed to
+1. host/port for the node - **udp://localhost:10002**
+2. id for the node - **2**
+
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneNode -Dexec.args="udp://localhost:10002
2 udp://localhost:10000 0”
+```
+
+Now the lists of live nodes for the cluster converge to reflect each node's connections to
the other two nodes.
+
+To see a node moved to the dead list. Kill the process in one of the running terminals: enter
control-c in the terminal window.
+Then the live-dead list of the two remaining nodes will converge to show one node live and
one node dead. 
+Start the missing node again, and it will again appear in the live list. 
+Note, that it does not matter which node goes dormant, every live node (eventually) communicates
with some other 
+live node in the cluster and gets the necessary updated status information.
+
+If you read the code, you will see that it defines a cluster (name = 'mycluster') and a number
of other setup details. See the video for
+a more complete description of the setup and for a more details description of the interactions
among the nodes.
+
+Also note, that the process of running these nodes produces a set of JSON files recording
node state (in the 'base' directory from where the node
+running). This enables a quicker startup as failed nodes recover. In this example, to recover
a node that you have killed, 
+using control-c, simply re-issue the command to run the node.
+
+
+Running org.apache.gossip.examples.StandAloneNodeCrdtOrSet
+----------------------------------------------------------
+This second example illustrates the using the data layer to share structured information:
a shared representation of a set
+of strings, and a shared counter. The objects representing those shared values are special
cases of a Conflict-free Replicated
+Data Type (hence, CRDT). 
+
+Here is the problem that is solved by these CRDT objects: since each node in a cluster can
message any other node in the cluster
+in any order, the messages that reflect the content of data structure can arrive in any order.
For example, one node may add an object
+to the set and send that modified set to another node that removes that object and sends
that message to a third node. If the first node
+also sends a message to the third node (with the object in the set), the third node could
receive conflicting information. But the CRDT
+data structures always contain enough information to resolve the conflict.
+
+As with the first demo there is a You Tube video that illustrates the problem and shows how
it is resolved and illustrates the running
+example: [https://www.youtube.com/watch?v=SqkJs0QDRdk](https://www.youtube.com/watch?v=SqkJs0QDRdk)
.
+
+Again, we will run three instances of the example, to illustrate the actions of the nodes
in the cluster. 
+The arguments to the application are identical to those in the
+first example. The difference in this example is that each node will read "commands" the
change the local state of its information. Which we 
+will illustrate shortly. But first, lets get the three nodes running:
+
+In the first terminal window:
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneNodeCrdtOrSet -Dexec.args="udp://localhost:10000
0 udp://localhost:10000 0"
+```
+
+In the second terminal window:
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneNodeCrdtOrSet -Dexec.args="udp://localhost:10001
1 udp://localhost:10000 0"
+```
+
+In the third terminal window:
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneNodeCrdtOrSet -Dexec.args="udp://localhost:10002
2 udp://localhost:10000 0"
+```
+
+Now, at any of the terminal windows, you can type a command from the following set of commands
to change the data that is stored locally. 
+Note, while you are typing, the terminal output continues, forcing you to type blind, but
when you hit the return, to end
+the input line, the input will be briefly displayed before scrolling off the screen.
+
+When you type one of these commands, you can then watch the propagation of that data through
the cluster. The commands are:
+```
+a string
+r string
+g number
+```
+* **a** is the 'add' command; it adds the string to the shared set - you should see the set
displayed with the new value, 
+    eventually, at all nodes.
+* **r** is the 'remove' command; it removes the string from the set (if it exists in the
set) - you should see the 
+	value eventually leave the set at all nodes
+* **g** is the "global increment" command; it assume that it's argument is a number and adds
that number to an accumulator.
+    Eventually, the accumulator at all nodes will settle to the same value.
+
+The CRDT representations of these values assure that all nodes will reach the same end state
for the resulting value regardless of the order
+of arrival of information from other nodes in the cluster.
+
+As an augmentation to the video, this [wikipedia article](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type),
+describing various CRDT representations and their usefulness, as well as some information
about interesting applications.
+
+
+Running org.apache.gossip.examples.StandAloneDatacenterAndRack
+--------------------------------------------------------------
+
+This final example illustrates more fine grained control over the expected "responsiveness"
of nodes in the cluster. 
+
+Apache gossip is designed as a library intended to be embedded in applications which to take
advantage of the gossip-protocol 
+for peer-to-peer communications. The effectiveness of communications among nodes in a gossip
cluster can be tuned
+to the expected latency of message transmission and expected responsiveness of other nodes
in the network. This example illustrates
+one model of this type of control: a "data center and rack" model of node distribution. In
this model, nodes that are in the same
+'data center' (perhaps on a different 'rack') are assumed to  have very lower latency and
high fidelity of communications. 
+While, nodes in different data centers are assumed to require more time to communicate, and
be subject to
+a higher rate of communication failure, so communications can be tuned to tolerate more variation
in latency and success of
+transmission, but this result in a longer "settle" time.
+
+Accordingly, the application in this example has a couple of extra arguments, a data center
id, and a rack id. 
+
+To start the first node (in the first terminal window), type the following:
+
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneDatacenterAndRack -Dexec.args="udp://localhost:10000
0 udp://localhost:10000 0 1 2"
+```
+The first four arguments are the same as in the other two examples, and the last two arguments
are the new arguments:
+1. The URI (host and port) for the node - **udp://localhost:10000**
+2. The id for the node - **0**
+3. The URI for a "seed" node - **udp://localhost:10000**
+4. The id for that seed node - **0**
+5. The data center id - **1**
+6. The rack id - **2**
+
+Lets then, set up two additional nodes (each in a separate terminal window), one in the same
data center on a different rack,
+and the other in a different data center. 
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneDatacenterAndRack -Dexec.args="udp://localhost:10001
1 udp://localhost:10000 0 1 3"
+```
+
+```
+cd incubator-gossip/gossip-examples
+mvn exec:java -Dexec.mainClass=org.apache.gossip.examples.StandAloneDatacenterAndRack -Dexec.args="udp://localhost:10002
2 udp://localhost:10000 0 2 2"
+```
+
+Now, the application running in the first terminal window, is identified as running in data
center 1 and on rack 2;
+the application in the second terminal window is running in the same data center in a different
rack (data center 1, rack 3).
+While, the application in the third terminal is running in a different data center (data
center 2). 
+
+If you stop the node in the first terminal window (control-c) you will observe that the process
in the third terminal window
+takes longer to settle to the correct state then the process in the second terminal window,
because it is expecting
+a greater latency in message transmission and is (therefore) more tolerant to delays (and
drops) in messaging, taking it
+longer to detect that the killed process is "off line".
+
+Final Notes
+-----------
+
+That concludes the description of running the examples.
+
+This project is an Apache [incubator project](http://incubator.apache.org/projects/gossip.html).

+The [official web site](http://gossip.incubator.apache.org/community/) has much additional
information: 
+see especially 'get involved' under 'community'. Enjoy, and please let us know if you are
finding this library helpful in any way.
+

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/9c9d96e5/gossip-examples/pom.xml
----------------------------------------------------------------------
diff --git a/gossip-examples/pom.xml b/gossip-examples/pom.xml
new file mode 100644
index 0000000..2246eba
--- /dev/null
+++ b/gossip-examples/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+	license agreements. See the NOTICE file distributed with this work for additional 
+	information regarding copyright ownership. The ASF licenses this file to 
+	You under the Apache License, Version 2.0 (the "License"); you may not use 
+	this file except in compliance with the License. You may obtain a copy of 
+	the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+	by applicable law or agreed to in writing, software distributed under the 
+	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+	OF ANY KIND, either express or implied. See the License for the specific 
+	language governing permissions and limitations under the License. -->
+<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>
+	</parent>
+
+	<name>Gossip Examples</name>
+	<artifactId>gossip-examples</artifactId>
+
+	<version>0.1.3-incubating-SNAPSHOT</version>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.gossip</groupId>
+			<artifactId>gossip-base</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.gossip</groupId>
+			<artifactId>gossip-protocol-jackson</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.gossip</groupId>
+			<artifactId>gossip-transport-udp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/9c9d96e5/gossip-examples/src/main/java/org/apache/gossip/examples/ExampleCommon.java
----------------------------------------------------------------------
diff --git a/gossip-examples/src/main/java/org/apache/gossip/examples/ExampleCommon.java b/gossip-examples/src/main/java/org/apache/gossip/examples/ExampleCommon.java
new file mode 100644
index 0000000..279bff1
--- /dev/null
+++ b/gossip-examples/src/main/java/org/apache/gossip/examples/ExampleCommon.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.examples;
+
+public class ExampleCommon {
+
+  private boolean clearTerminalScreen = true;
+
+  /*
+   * Look for -s in args. If there, suppress terminal-clear on write results Shift args for
+   * positional args, if necessary
+   */
+  public String[] checkArgsForClearFlag(String[] args) {
+    int pos = 0;
+    for (int i = 0; i < args.length; i++) {
+      if (args[i].equals("-s")) {
+        clearTerminalScreen = false;
+      } else {
+        // in the case of the -s flag, shift args 
+        // down by one slot; this will end up with
+        // a duplicate entry in the last position of args,
+        // but this is ok, because it will be ignored
+        args[pos++] = args[i];
+      }
+    }
+    return args;
+  }
+
+  public void optionallyClearTerminal() {
+    if (clearTerminalScreen) {
+      System.out.print("\033[H\033[2J");
+      System.out.flush();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/9c9d96e5/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
----------------------------------------------------------------------
diff --git a/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
new file mode 100644
index 0000000..1a2643c
--- /dev/null
+++ b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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 {
+
+  private static ExampleCommon common = new ExampleCommon();
+
+  public static void main(String[] args) throws UnknownHostException, InterruptedException
{
+    args = common.checkArgsForClearFlag(args);
+    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) {
+      common.optionallyClearTerminal();
+      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/9c9d96e5/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNode.java
----------------------------------------------------------------------
diff --git a/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNode.java
b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNode.java
new file mode 100644
index 0000000..70c3e4d
--- /dev/null
+++ b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNode.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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 {
+
+  private static ExampleCommon common = new ExampleCommon();
+
+  public static void main(String[] args) throws UnknownHostException, InterruptedException
{
+    args = common.checkArgsForClearFlag(args);
+    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) {
+      common.optionallyClearTerminal();
+      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/9c9d96e5/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
----------------------------------------------------------------------
diff --git a/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
new file mode 100644
index 0000000..7d4db93
--- /dev/null
+++ b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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 {
+
+  private static ExampleCommon common = new ExampleCommon();
+
+  public static void main(String[] args) throws InterruptedException, IOException {
+    args = common.checkArgsForClearFlag(args);
+    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) {
+        common.optionallyClearTerminal();
+        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/9c9d96e5/gossip-itest/.gitignore
----------------------------------------------------------------------
diff --git a/gossip-itest/.gitignore b/gossip-itest/.gitignore
new file mode 100644
index 0000000..f538c88
--- /dev/null
+++ b/gossip-itest/.gitignore
@@ -0,0 +1,5 @@
+# json files generated with running examples in this module
+pernodedata.*.*.json
+ringstate.*.*.json
+shareddata.*.*.json
+

http://git-wip-us.apache.org/repos/asf/incubator-gossip/blob/9c9d96e5/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 1c48306..8740319 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,6 +59,7 @@
 		<module>gossip-transport-udp</module>
 		<module>gossip-protocol-jackson</module>
 		<module>gossip-itest</module>
+		<module>gossip-examples</module>
 	</modules>
 	
 	<description>A peer to peer cluster discovery service</description>
@@ -195,8 +196,10 @@
 				<artifactId>apache-rat-plugin</artifactId>
 				<configuration>
 					<excludes>
-						<exclude>README.md</exclude>
+						<exclude>**/README.md</exclude>
 						<exclude>eclipse_template.xml</exclude>
+						<!--  files generated by running the examples in gossip-examples  -->
+						<exclued>**/*.mycluster.*.json</exclued>
 					</excludes>
 				</configuration>
 				<executions>



Mime
View raw message