Merge branch 'release/1.6.0'
diff --git a/KEYS b/KEYS
index 4886ba9..b085a1b 100644
--- a/KEYS
+++ b/KEYS
@@ -1025,3 +1025,62 @@
 A4DF9y+6usA=
 =O5OI
 -----END PGP PUBLIC KEY BLOCK-----
+pub   rsa4096 2018-04-12 [SC] [expires: 2022-04-12]
+      876331B45A97E382D1BDFB4444820F9CABF4396F
+uid           [ultimate] Mike Stolz <mikestolz@apache.org>
+sig 3        44820F9CABF4396F 2018-04-12  Mike Stolz <mikestolz@apache.org>
+sub   rsa4096 2018-04-12 [E] [expires: 2022-04-12]
+sig          44820F9CABF4396F 2018-04-12  Mike Stolz <mikestolz@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+3Uy9JDi1mbJK
+=IZaJ
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/README.md b/README.md
index 2aad532..7718197 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@
 *  [Cache Listeners](listener/README.md)
 *  [Async Event Queues & Async Event Listeners](async/README.md)
 *  Continuous Querying
-*  Transactions
+*  [Transaction](transaction/README.md)
 *  [Eviction](eviction/README.md)
 *  [Expiration](expiration/README.md)
 *  Overflow
@@ -85,6 +85,7 @@
 
 ### Advanced
 
+*  [Lucene Spatial Indexing](luceneSpatial/README.md)
 *  WAN Gateway
 *  Durable subscriptions
 *  Delta propagation
diff --git a/build.gradle b/build.gradle
index d748a98..d148d2c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -105,12 +105,13 @@
     environment 'PATH', geodePath
     ignoreExitValue true
     commandLine 'sh', '-c', "" +
-            "TIMEOUT=10 ;" +
+            "TIMEOUT=120 ;" +
             "echo \"Waiting at most \$TIMEOUT seconds for all members to shut down...\" ;" +
-            "while pgrep -f \"(Server|Locator)Launcher\" > /dev/null ; do  printf \".\" ; " +
+            "while pgrep -f \"(Server|Locator)Launcher\" > /dev/null ; do" +
+            "  printf \".\" ; " +
             "  sleep 1 ;" +
             "  TIMEOUT=\$((\$TIMEOUT - 1)) ;" +
-            "  if [[ \$TIMEOUT -eq 0 ]] ; then" +
+            "  if [ \$TIMEOUT -eq 0 ] ; then" +
             "    echo \"\" ;" +
             "    exit 10 ;" +
             "  fi ;" +
@@ -131,7 +132,8 @@
     environment 'GEODE_HOME', installDir
     environment 'PATH', geodePath
     ignoreExitValue true
-    commandLine 'sh', '-c', "pgrep -f \"(Server|Locator)Launcher\" > /dev/null ; "
+    commandLine 'sh', '-c', "echo \"Looking for existing member processes...\" ; " +
+            "pgrep -f \"(Server|Locator)Launcher\" ; "
     doLast {
       if (execResult.exitValue == 0) {
         throw new GradleException("Existing members detected.  Examples expect a clean environment in which to run.")
diff --git a/gradle.properties b/gradle.properties
index 054dabb..82d5d8c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -14,8 +14,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-version = 1.5.0
-geodeVersion = 1.5.0
+version = 1.6.0
+geodeVersion = 1.6.0
 
 # release properties, set these on the command line to validate against
 # a release candidate
diff --git a/gradle/release.gradle b/gradle/release.gradle
index 526ebeb..5b1d677 100644
--- a/gradle/release.gradle
+++ b/gradle/release.gradle
@@ -30,7 +30,6 @@
     it.name.toLowerCase().contains("dist")
   }.each { archive ->
     archive.doLast {
-      ant.checksum file:"${archive.archivePath}", algorithm:"md5", format: 'MD5SUM'
       ant.checksum file:"${archive.archivePath}", algorithm:"sha-256", format: 'MD5SUM', fileext:".sha256"
       signing {
         required { project.hasProperty("signArchives") }
diff --git a/settings.gradle b/settings.gradle
index d23bb7e..86ebb89 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -33,3 +33,4 @@
 include 'serialization'
 include 'expiration'
 include 'indexes'
+include 'transaction'
diff --git a/transaction/README.md b/transaction/README.md
new file mode 100644
index 0000000..c6b28c3
--- /dev/null
+++ b/transaction/README.md
@@ -0,0 +1,60 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Geode Transaction Example
+
+This is a simple example that demonstrates the use of [transactions](https://geode.apache.org/docs/guide/11/developing/transactions/working_with_transactions.html)
+to protect consistency during concurrent access and modification of data. Since a region may
+configured across multiple servers and multiple clients may interact with that region independent of
+each other, data integrity relies on synchronization of modifications between all actors.
+
+An example of how data can become inconsistent during concurrent interaction is as follows:
+ 1. Client A gets the value of a key.
+ 2. Client B gets the value of the same key.
+ 3. Client A puts a new value for the key based upon the original value.
+ 4. Client B puts a different new value for the key based upon the original value.
+The final value for that key is based upon the original value, _not_ the updated value from Client
+A. For the final value to contain all the calculations from both clients, both the access and the
+modification of the value would need to happen as an atomic action across the region.
+
+This example starts five child processes, each of which tries one thousand times to get the current
+value of a counter, increment that value, and the put the incremented value back into the region.
+To protect data consistency, the incrementing is abandoned and retried if another child has already
+incremented the value _or_ if another child is simultaenously trying to increment the value. This
+example, which should take about a dozen seconds, reports the final value of the counter to show
+that all of the children's increments were consistently applied.
+
+This example assumes you have installed Java and Geode.
+
+## Steps
+
+1. From the `geode-examples/transaction` directory, build the example and
+   run unit tests.
+
+        $ ../gradlew build
+
+2. Next start a locator, start a server, and create a region.
+
+        $ gfsh run --file=scripts/start.gfsh
+
+3. Run the example to demonstrate transactions.
+
+        $ ../gradlew run
+
+4. Shut down the system.
+
+        $ gfsh run --file=scripts/stop.gfsh
diff --git a/transaction/scripts/start.gfsh b/transaction/scripts/start.gfsh
new file mode 100755
index 0000000..94e14a5
--- /dev/null
+++ b/transaction/scripts/start.gfsh
@@ -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.
+#
+
+start locator --name=locator --bind-address=127.0.0.1
+start server --name=server1 --locators=127.0.0.1[10334] --server-port=0 --classpath=../build/classes/main
+start server --name=server2 --locators=127.0.0.1[10334] --server-port=0 --classpath=../build/classes/main
+list members
+
+create region --name=example-region --type=REPLICATE --skip-if-exists=true
+describe region --name=example-region
diff --git a/transaction/scripts/stop.gfsh b/transaction/scripts/stop.gfsh
new file mode 100755
index 0000000..15cd93c
--- /dev/null
+++ b/transaction/scripts/stop.gfsh
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+connect --locator=127.0.0.1[10334]
+shutdown --include-locators=true
diff --git a/transaction/src/main/java/org/apache/geode_examples/transaction/Example.java b/transaction/src/main/java/org/apache/geode_examples/transaction/Example.java
new file mode 100644
index 0000000..64428e4
--- /dev/null
+++ b/transaction/src/main/java/org/apache/geode_examples/transaction/Example.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode_examples.transaction;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Example {
+  public static final int INCREMENTS = 1000;
+
+  public static final String REGION_NAME = "example-region";
+
+  public static final String KEY = "counter";
+
+  final Region<String, Integer> region;
+
+  final Map<Integer, Process> children = new HashMap<>();
+
+  static String constructJVMPath() {
+    StringBuilder builder = new StringBuilder();
+    builder.append(System.getProperty("java.home"));
+    builder.append(File.separator);
+    builder.append("bin");
+    builder.append(File.separator);
+    builder.append("java");
+    if (System.getProperty("os.name").toLowerCase().contains("win")) {
+      builder.append("w.exe");
+    }
+    return builder.toString();
+  }
+
+  public static void main(String[] args) {
+    // connect to the locator using default port 10334
+    ClientCache cache = new ClientCacheFactory().addPoolLocator("127.0.0.1", 10334)
+        .set("log-level", "WARN").create();
+
+    // create a local region that matches the server region
+    ClientRegionFactory<String, Integer> clientRegionFactory =
+        cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+    Region<String, Integer> region = clientRegionFactory.create(REGION_NAME);
+
+    Example example = new Example(region);
+    example.initializeEntry();
+    example.executeChildProcesses(5);
+
+    cache.close();
+  }
+
+  Example(Region<String, Integer> region) {
+    this.region = region;
+  }
+
+  void executeChildProcess(int id) {
+    String[] command = new String[5];
+    command[0] = constructJVMPath();
+    command[1] = "-classpath";
+    command[2] = System.getProperty("java.class.path") + ":build/libs/transaction.jar";
+    command[3] = "org.apache.geode_examples.transaction.Incrementer";
+    command[4] = Integer.toString(id);
+    try {
+      children.put(id, Runtime.getRuntime().exec(command));
+      System.out.println("Executed child " + id);
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+  }
+
+  void executeChildProcesses(int numberOfIncrementers) {
+    System.out.println("Expected value of counter: " + (numberOfIncrementers * INCREMENTS));
+
+    for (int i = 0; i < numberOfIncrementers; ++i) {
+      executeChildProcess(i + 1);
+    }
+
+    for (Map.Entry<Integer, Process> child : children.entrySet()) {
+      System.out.println("Waiting for " + child.getKey() + "...");
+      try {
+        child.getValue().waitFor();
+        System.out.println("Reaped child " + child.getKey());
+      } catch (InterruptedException ie) {
+        ie.printStackTrace();
+      }
+    }
+
+    System.out.println("Actual value of counter:   " + region.get(KEY));
+  }
+
+  void initializeEntry() {
+    region.put(KEY, 0);
+  }
+}
diff --git a/transaction/src/main/java/org/apache/geode_examples/transaction/Incrementer.java b/transaction/src/main/java/org/apache/geode_examples/transaction/Incrementer.java
new file mode 100644
index 0000000..36e8497
--- /dev/null
+++ b/transaction/src/main/java/org/apache/geode_examples/transaction/Incrementer.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode_examples.transaction;
+
+import org.apache.geode.cache.CacheTransactionManager;
+import org.apache.geode.cache.CommitConflictException;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+
+public class Incrementer {
+  final int id;
+  final ClientCache cache;
+  final Region<String, Integer> region;
+
+  Incrementer(int id, ClientCache cache, Region<String, Integer> region) {
+    this.id = id;
+    this.cache = cache;
+    this.region = region;
+  }
+
+  public static void main(String[] args) {
+    // connect to the locator using default port 10334
+    ClientCache cache = new ClientCacheFactory().addPoolLocator("127.0.0.1", 10334)
+        .set("log-level", "WARN").create();
+
+    // create a local region that matches the server region
+    ClientRegionFactory<String, Integer> clientRegionFactory =
+        cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+    Region<String, Integer> region = clientRegionFactory.create(Example.REGION_NAME);
+
+    Incrementer incrementer = new Incrementer(Integer.parseInt(args[0]), cache, region);
+    incrementer.incrementEntry();
+
+    cache.close();
+  }
+
+  void incrementEntry() {
+    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
+    for (int i = 0; i < Example.INCREMENTS; ++i) {
+      boolean incremented = false;
+      while (!incremented) {
+        try {
+          cacheTransactionManager.begin();
+          final Integer oldValue = region.get(Example.KEY);
+          final Integer newValue = oldValue + 1;
+          region.put(Example.KEY, newValue);
+          cacheTransactionManager.commit();
+          incremented = true;
+        } catch (CommitConflictException cce) {
+          // Do nothing.
+        }
+      }
+    }
+  }
+}