From 9c9d96e564eca1513a9776b9eba24d52787500d2 Mon Sep 17 00:00:00 2001 From: Terry Weymouth Date: Mon, 29 May 2017 09:16:32 -0400 Subject: [PATCH] GOSSIP-86 Examples in separate module - Added Readme. --- README.md | 4 + gossip-examples/.gitignore | 2 + gossip-examples/README.md | 246 ++++++++++++++++++ gossip-examples/pom.xml | 45 ++++ .../apache/gossip/examples/ExampleCommon.java | 50 ++++ .../examples/StandAloneDatacenterAndRack.java | 15 +- .../gossip/examples/StandAloneNode.java | 16 +- .../examples/StandAloneNodeCrdtOrSet.java | 67 ++--- gossip-itest/.gitignore | 5 + pom.xml | 5 +- 10 files changed, 414 insertions(+), 41 deletions(-) create mode 100644 gossip-examples/.gitignore create mode 100644 gossip-examples/README.md create mode 100644 gossip-examples/pom.xml create mode 100644 gossip-examples/src/main/java/org/apache/gossip/examples/ExampleCommon.java rename {gossip-base => gossip-examples}/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java (82%) rename {gossip-base => gossip-examples}/src/main/java/org/apache/gossip/examples/StandAloneNode.java (79%) rename {gossip-base => gossip-examples}/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java (71%) create mode 100644 gossip-itest/.gitignore 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 ----- 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 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. + 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 @@ + + + + 4.0.0 + + + org.apache.gossip + gossip-parent + 0.1.3-incubating-SNAPSHOT + + + Gossip Examples + gossip-examples + + 0.1.3-incubating-SNAPSHOT + + + + org.apache.gossip + gossip-base + ${project.version} + + + org.apache.gossip + gossip-protocol-jackson + ${project.version} + + + org.apache.gossip + gossip-transport-udp + ${project.version} + + + + \ No newline at end of file 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(); + } + } +} diff --git a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java similarity index 82% rename from gossip-base/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java rename to gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java index 497894c..1a2643c 100644 --- a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java +++ b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneDatacenterAndRack.java @@ -32,7 +32,10 @@ import org.apache.gossip.manager.GossipManagerBuilder; public class StandAloneDatacenterAndRack { - public static void main (String [] args) throws UnknownHostException, InterruptedException { + 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); @@ -44,19 +47,21 @@ public class StandAloneDatacenterAndRack { Map props = new HashMap<>(); props.put(DatacenterRackAwareActiveGossiper.DATACENTER, args[4]); props.put(DatacenterRackAwareActiveGossiper.RACK, args[5]); - GossipManager manager = GossipManagerBuilder.newBuilder() - .cluster("mycluster") + 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]))) + .gossipMembers( + Arrays.asList(new RemoteMember("mycluster", URI.create(args[2]), args[3]))) .properties(props) .build(); manager.init(); - while (true){ + while (true) { + common.optionallyClearTerminal(); System.out.println("Live: " + manager.getLiveMembers()); System.out.println("Dead: " + manager.getDeadMembers()); Thread.sleep(2000); } } + } diff --git a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNode.java b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNode.java similarity index 79% rename from gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNode.java rename to gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNode.java index 93421b1..70c3e4d 100644 --- a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNode.java +++ b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNode.java @@ -26,22 +26,28 @@ import org.apache.gossip.manager.GossipManager; import org.apache.gossip.manager.GossipManagerBuilder; public class StandAloneNode { - public static void main (String [] args) throws UnknownHostException, InterruptedException{ + + 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") + 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]))) + .gossipMembers( + Arrays.asList(new RemoteMember("mycluster", URI.create(args[2]), args[3]))) .gossipSettings(s) .build(); gossipService.init(); - while (true){ + while (true) { + common.optionallyClearTerminal(); System.out.println("Live: " + gossipService.getLiveMembers()); System.out.println("Dead: " + gossipService.getDeadMembers()); Thread.sleep(2000); } } + } diff --git a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java similarity index 71% rename from gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java rename to gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java index d78cf5e..7d4db93 100644 --- a/gossip-base/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java +++ b/gossip-examples/src/main/java/org/apache/gossip/examples/StandAloneNodeCrdtOrSet.java @@ -31,56 +31,62 @@ import org.apache.gossip.manager.GossipManagerBuilder; import org.apache.gossip.model.SharedDataMessage; public class StandAloneNodeCrdtOrSet { - public static void main (String [] args) throws InterruptedException, IOException{ + + 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") + 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]))) + .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) {} + 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){ + 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'){ + if (op == 'a') { addData(val, gossipService); } else if (op == 'r') { removeData(val, gossipService); - } else if (op == 'g'){ + } else if (op == 'g') { gcount(val, gossipService); } } } } - - private static void gcount(String val, GossipManager gossipManager){ + + private static void gcount(String val, GossipManager gossipManager) { GrowOnlyCounter c = (GrowOnlyCounter) gossipManager.findCrdt("def"); Long l = Long.valueOf(val); - if (c == null){ + if (c == null) { c = new GrowOnlyCounter(new GrowOnlyCounter.Builder(gossipManager).increment((l))); } else { c = new GrowOnlyCounter(c, new GrowOnlyCounter.Builder(gossipManager).increment((l))); @@ -92,19 +98,19 @@ public class StandAloneNodeCrdtOrSet { m.setTimestamp(System.currentTimeMillis()); gossipManager.merge(m); } - - private static void removeData(String val, GossipManager gossipService){ + + private static void removeData(String val, GossipManager gossipService) { @SuppressWarnings("unchecked") OrSet s = (OrSet) gossipService.findCrdt("abc"); SharedDataMessage m = new SharedDataMessage(); m.setExpireAt(Long.MAX_VALUE); m.setKey("abc"); - m.setPayload(new OrSet(s , new OrSet.Builder().remove(val))); + m.setPayload(new OrSet(s, new OrSet.Builder().remove(val))); m.setTimestamp(System.currentTimeMillis()); gossipService.merge(m); } - - private static void addData(String val, GossipManager gossipService){ + + private static void addData(String val, GossipManager gossipService) { SharedDataMessage m = new SharedDataMessage(); m.setExpireAt(Long.MAX_VALUE); m.setKey("abc"); @@ -112,4 +118,5 @@ public class StandAloneNodeCrdtOrSet { m.setTimestamp(System.currentTimeMillis()); gossipService.merge(m); } + } 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 + diff --git a/pom.xml b/pom.xml index 1c48306..8740319 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,7 @@ gossip-transport-udp gossip-protocol-jackson gossip-itest + gossip-examples A peer to peer cluster discovery service @@ -195,8 +196,10 @@ apache-rat-plugin - README.md + **/README.md eclipse_template.xml + + **/*.mycluster.*.json