You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sa...@apache.org on 2016/01/15 12:44:37 UTC

[1/6] cassandra git commit: Add custom 2i validation method which uses base CFMetaData

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 97e8953ec -> 5e5ea772e
  refs/heads/cassandra-3.3 b48d71cc6 -> 501f75bf9
  refs/heads/trunk b719cff71 -> 75f78729d


Add custom 2i validation method which uses base CFMetaData

Patch by Andrés de la Peña; reviewed by Sam Tunnicliffe for
CASSANDRA-10924


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5e5ea772
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5e5ea772
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5e5ea772

Branch: refs/heads/cassandra-3.0
Commit: 5e5ea772ed346b5197a6a7be3046953686a8975a
Parents: 97e8953
Author: Andrés de la Peña <ad...@stratio.com>
Authored: Tue Jan 12 15:11:37 2016 +0000
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Fri Jan 15 11:13:19 2016 +0000

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../org/apache/cassandra/config/CFMetaData.java |  2 +-
 src/java/org/apache/cassandra/index/Index.java  | 21 +++++---
 .../apache/cassandra/schema/IndexMetadata.java  | 20 +++++--
 .../apache/cassandra/index/CustomIndexTest.java | 57 ++++++++++++++++++++
 5 files changed, 88 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 8c3527f..ff607a5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.3
+ * Support passing base table metadata to custom 2i validation (CASSANDRA-10924)
  * Ensure stale index entries are purged during reads (CASSANDRA-11013)
  * Fix AssertionError when removing from list using UPDATE (CASSANDRA-10954)
  * Fix UnsupportedOperationException when reading old sstable with range

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java
index 62b2369..cb6d3b8 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -877,7 +877,7 @@ public final class CFMetaData
                 throw new ConfigurationException("Duplicate index name " + index.name);
             indexNames.add(index.name);
 
-            index.validate();
+            index.validate(this);
         }
 
         return this;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/index/Index.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/index/Index.java b/src/java/org/apache/cassandra/index/Index.java
index 084d0e3..71dcfc9 100644
--- a/src/java/org/apache/cassandra/index/Index.java
+++ b/src/java/org/apache/cassandra/index/Index.java
@@ -89,16 +89,21 @@ import org.apache.cassandra.utils.concurrent.OpOrder;
  * The post processing function is obtained from the Index's postProcessorFor method; the built-in indexes which ship
  * with Cassandra return a no-op function here.
  *
- * An optional static method may be provided to validate custom index options:
+ * An optional static method may be provided to validate custom index options (two variants are supported):
  *
- * <pre> {@code
- * public static Map<String, String> validateOptions(Map<String, String> options);
- * } </pre>
+ * <pre>{@code public static Map<String, String> validateOptions(Map<String, String> options);</pre>
  *
- * The input is the map of index options supplied in the WITH clause of a CREATE INDEX statement. The method should
- * return a map containing any of the supplied options which are not valid for the implementation. If the returned
- * map is not empty, validation is considered failed and an error is raised. Alternatively, the implementation may
- * choose to throw an org.apache.cassandra.exceptions.ConfigurationException if invalid options are encountered.
+ * The input is the map of index options supplied in the WITH clause of a CREATE INDEX statement.
+ *
+ * <pre>{@code public static Map<String, String> validateOptions(Map<String, String> options, CFMetaData cfm);}</pre>
+ *
+ * In this version, the base table's metadata is also supplied as an argument.
+ * If both overloaded methods are provided, only the one including the base table's metadata will be invoked.
+ *
+ * The validation method should return a map containing any of the supplied options which are not valid for the
+ * implementation. If the returned map is not empty, validation is considered failed and an error is raised.
+ * Alternatively, the implementation may choose to throw an org.apache.cassandra.exceptions.ConfigurationException
+ * if invalid options are encountered.
  *
  */
 public interface Index

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/schema/IndexMetadata.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/IndexMetadata.java b/src/java/org/apache/cassandra/schema/IndexMetadata.java
index ee9179a..7c60a64 100644
--- a/src/java/org/apache/cassandra/schema/IndexMetadata.java
+++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java
@@ -138,7 +138,7 @@ public final class IndexMetadata
             return (cfName + "_" + root + "_idx").replaceAll("\\W", "");
     }
 
-    public void validate()
+    public void validate(CFMetaData cfm)
     {
         if (!isNameValid(name))
             throw new ConfigurationException("Illegal index name " + name);
@@ -155,11 +155,14 @@ public final class IndexMetadata
             Class<Index> indexerClass = FBUtilities.classForName(className, "custom indexer");
             if(!Index.class.isAssignableFrom(indexerClass))
                 throw new ConfigurationException(String.format("Specified Indexer class (%s) does not implement the Indexer interface", className));
-            validateCustomIndexOptions(indexerClass, options);
+            validateCustomIndexOptions(cfm, indexerClass, options);
         }
     }
 
-    private void validateCustomIndexOptions(Class<? extends Index> indexerClass, Map<String, String> options) throws ConfigurationException
+    private void validateCustomIndexOptions(CFMetaData cfm,
+                                            Class<? extends Index> indexerClass,
+                                            Map<String, String> options)
+    throws ConfigurationException
     {
         try
         {
@@ -169,7 +172,16 @@ public final class IndexMetadata
             if (filteredOptions.isEmpty())
                 return;
 
-            Map<?,?> unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class).invoke(null, filteredOptions);
+            Map<?,?> unknownOptions;
+            try
+            {
+                unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class, CFMetaData.class).invoke(null, filteredOptions, cfm);
+            }
+            catch (NoSuchMethodException e)
+            {
+                unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class).invoke(null, filteredOptions);
+            }
+
             if (!unknownOptions.isEmpty())
                 throw new ConfigurationException(String.format("Properties specified %s are not understood by %s", unknownOptions.keySet(), indexerClass.getSimpleName()));
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/test/unit/org/apache/cassandra/index/CustomIndexTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/index/CustomIndexTest.java b/test/unit/org/apache/cassandra/index/CustomIndexTest.java
index b305868..3bfb6a5 100644
--- a/test/unit/org/apache/cassandra/index/CustomIndexTest.java
+++ b/test/unit/org/apache/cassandra/index/CustomIndexTest.java
@@ -32,6 +32,7 @@ import org.apache.cassandra.utils.FBUtilities;
 import static org.apache.cassandra.Util.throwAssert;
 import static org.apache.cassandra.cql3.statements.IndexTarget.CUSTOM_INDEX_OPTION_NAME;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -504,6 +505,28 @@ public class CustomIndexTest extends CQLTester
             assertEquals(index.rowsDeleted.get(i).clustering(), index.rowsInserted.get(i).clustering());
     }
 
+    @Test
+    public void validateOptions() throws Throwable
+    {
+        createTable("CREATE TABLE %s(k int, c int, v1 int, v2 int, PRIMARY KEY(k,c))");
+        createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c, v2) USING '%s' WITH OPTIONS = {'foo':'bar'}",
+                                  IndexWithValidateOptions.class.getName()));
+        assertNotNull(IndexWithValidateOptions.options);
+        assertEquals("bar", IndexWithValidateOptions.options.get("foo"));
+    }
+
+    @Test
+    public void validateOptionsWithCFMetaData() throws Throwable
+    {
+        createTable("CREATE TABLE %s(k int, c int, v1 int, v2 int, PRIMARY KEY(k,c))");
+        createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c, v2) USING '%s' WITH OPTIONS = {'foo':'bar'}",
+                                  IndexWithOverloadedValidateOptions.class.getName()));
+        CFMetaData cfm = getCurrentColumnFamilyStore().metadata;
+        assertEquals(cfm, IndexWithOverloadedValidateOptions.cfm);
+        assertNotNull(IndexWithOverloadedValidateOptions.options);
+        assertEquals("bar", IndexWithOverloadedValidateOptions.options.get("foo"));
+    }
+
     private void testCreateIndex(String indexName, String... targetColumnNames) throws Throwable
     {
         createIndex(String.format("CREATE CUSTOM INDEX %s ON %%s(%s) USING '%s'",
@@ -672,4 +695,38 @@ public class CustomIndexTest extends CQLTester
             throw new InvalidRequestException("None shall pass");
         }
     }
+
+    public static final class IndexWithValidateOptions extends StubIndex
+    {
+        public static Map<String, String> options;
+
+        public IndexWithValidateOptions(ColumnFamilyStore baseCfs, IndexMetadata metadata)
+        {
+            super(baseCfs, metadata);
+        }
+
+        public static Map<String, String> validateOptions(Map<String, String> options)
+        {
+            IndexWithValidateOptions.options = options;
+            return new HashMap<>();
+        }
+    }
+
+    public static final class IndexWithOverloadedValidateOptions extends StubIndex
+    {
+        public static CFMetaData cfm;
+        public static Map<String, String> options;
+
+        public IndexWithOverloadedValidateOptions(ColumnFamilyStore baseCfs, IndexMetadata metadata)
+        {
+            super(baseCfs, metadata);
+        }
+
+        public static Map<String, String> validateOptions(Map<String, String> options, CFMetaData cfm)
+        {
+            IndexWithOverloadedValidateOptions.options = options;
+            IndexWithOverloadedValidateOptions.cfm = cfm;
+            return new HashMap<>();
+        }
+    }
 }


[6/6] cassandra git commit: Merge branch 'cassandra-3.3' into trunk

Posted by sa...@apache.org.
Merge branch 'cassandra-3.3' into trunk


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/75f78729
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/75f78729
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/75f78729

Branch: refs/heads/trunk
Commit: 75f78729d41c559ddd51581ffb530226181989b7
Parents: b719cff 501f75b
Author: Sam Tunnicliffe <sa...@beobal.com>
Authored: Fri Jan 15 11:38:09 2016 +0000
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Fri Jan 15 11:38:09 2016 +0000

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../org/apache/cassandra/config/CFMetaData.java |  2 +-
 src/java/org/apache/cassandra/index/Index.java  | 21 +++++---
 .../apache/cassandra/schema/IndexMetadata.java  | 20 +++++--
 .../apache/cassandra/index/CustomIndexTest.java | 57 ++++++++++++++++++++
 5 files changed, 88 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/75f78729/CHANGES.txt
----------------------------------------------------------------------


[4/6] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.3

Posted by sa...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.3


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/501f75bf
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/501f75bf
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/501f75bf

Branch: refs/heads/trunk
Commit: 501f75bf99b62f94839de995a8e778aabb500523
Parents: b48d71c 5e5ea772
Author: Sam Tunnicliffe <sa...@beobal.com>
Authored: Fri Jan 15 11:29:22 2016 +0000
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Fri Jan 15 11:29:22 2016 +0000

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../org/apache/cassandra/config/CFMetaData.java |  2 +-
 src/java/org/apache/cassandra/index/Index.java  | 21 +++++---
 .../apache/cassandra/schema/IndexMetadata.java  | 20 +++++--
 .../apache/cassandra/index/CustomIndexTest.java | 57 ++++++++++++++++++++
 5 files changed, 88 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 9bc1349,ff607a5..991077d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,9 -1,6 +1,10 @@@
 -3.0.3
 +3.3
 + * Avoid bootstrap hanging when existing nodes have no data to stream (CASSANDRA-11010)
 +Merged from 3.0:
+  * Support passing base table metadata to custom 2i validation (CASSANDRA-10924)
   * Ensure stale index entries are purged during reads (CASSANDRA-11013)
 + * (cqlsh) Also apply --connect-timeout to control connection
 +   timeout (CASSANDRA-10959)
   * Fix AssertionError when removing from list using UPDATE (CASSANDRA-10954)
   * Fix UnsupportedOperationException when reading old sstable with range
     tombstone (CASSANDRA-10743)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/src/java/org/apache/cassandra/index/Index.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/src/java/org/apache/cassandra/schema/IndexMetadata.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/schema/IndexMetadata.java
index 59ac1cf,7c60a64..04e06ab
--- a/src/java/org/apache/cassandra/schema/IndexMetadata.java
+++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java
@@@ -138,12 -133,12 +138,12 @@@ public final class IndexMetadat
      public static String getDefaultIndexName(String cfName, String root)
      {
          if (root == null)
 -            return (cfName + "_" + "idx").replaceAll("\\W", "");
 +            return PATTERN_NON_WORD_CHAR.matcher(cfName + "_" + "idx").replaceAll("");
          else
 -            return (cfName + "_" + root + "_idx").replaceAll("\\W", "");
 +            return PATTERN_NON_WORD_CHAR.matcher(cfName + "_" + root + "_idx").replaceAll("");
      }
  
-     public void validate()
+     public void validate(CFMetaData cfm)
      {
          if (!isNameValid(name))
              throw new ConfigurationException("Illegal index name " + name);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/test/unit/org/apache/cassandra/index/CustomIndexTest.java
----------------------------------------------------------------------


[3/6] cassandra git commit: Add custom 2i validation method which uses base CFMetaData

Posted by sa...@apache.org.
Add custom 2i validation method which uses base CFMetaData

Patch by Andrés de la Peña; reviewed by Sam Tunnicliffe for
CASSANDRA-10924


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5e5ea772
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5e5ea772
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5e5ea772

Branch: refs/heads/trunk
Commit: 5e5ea772ed346b5197a6a7be3046953686a8975a
Parents: 97e8953
Author: Andrés de la Peña <ad...@stratio.com>
Authored: Tue Jan 12 15:11:37 2016 +0000
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Fri Jan 15 11:13:19 2016 +0000

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../org/apache/cassandra/config/CFMetaData.java |  2 +-
 src/java/org/apache/cassandra/index/Index.java  | 21 +++++---
 .../apache/cassandra/schema/IndexMetadata.java  | 20 +++++--
 .../apache/cassandra/index/CustomIndexTest.java | 57 ++++++++++++++++++++
 5 files changed, 88 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 8c3527f..ff607a5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.3
+ * Support passing base table metadata to custom 2i validation (CASSANDRA-10924)
  * Ensure stale index entries are purged during reads (CASSANDRA-11013)
  * Fix AssertionError when removing from list using UPDATE (CASSANDRA-10954)
  * Fix UnsupportedOperationException when reading old sstable with range

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java
index 62b2369..cb6d3b8 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -877,7 +877,7 @@ public final class CFMetaData
                 throw new ConfigurationException("Duplicate index name " + index.name);
             indexNames.add(index.name);
 
-            index.validate();
+            index.validate(this);
         }
 
         return this;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/index/Index.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/index/Index.java b/src/java/org/apache/cassandra/index/Index.java
index 084d0e3..71dcfc9 100644
--- a/src/java/org/apache/cassandra/index/Index.java
+++ b/src/java/org/apache/cassandra/index/Index.java
@@ -89,16 +89,21 @@ import org.apache.cassandra.utils.concurrent.OpOrder;
  * The post processing function is obtained from the Index's postProcessorFor method; the built-in indexes which ship
  * with Cassandra return a no-op function here.
  *
- * An optional static method may be provided to validate custom index options:
+ * An optional static method may be provided to validate custom index options (two variants are supported):
  *
- * <pre> {@code
- * public static Map<String, String> validateOptions(Map<String, String> options);
- * } </pre>
+ * <pre>{@code public static Map<String, String> validateOptions(Map<String, String> options);</pre>
  *
- * The input is the map of index options supplied in the WITH clause of a CREATE INDEX statement. The method should
- * return a map containing any of the supplied options which are not valid for the implementation. If the returned
- * map is not empty, validation is considered failed and an error is raised. Alternatively, the implementation may
- * choose to throw an org.apache.cassandra.exceptions.ConfigurationException if invalid options are encountered.
+ * The input is the map of index options supplied in the WITH clause of a CREATE INDEX statement.
+ *
+ * <pre>{@code public static Map<String, String> validateOptions(Map<String, String> options, CFMetaData cfm);}</pre>
+ *
+ * In this version, the base table's metadata is also supplied as an argument.
+ * If both overloaded methods are provided, only the one including the base table's metadata will be invoked.
+ *
+ * The validation method should return a map containing any of the supplied options which are not valid for the
+ * implementation. If the returned map is not empty, validation is considered failed and an error is raised.
+ * Alternatively, the implementation may choose to throw an org.apache.cassandra.exceptions.ConfigurationException
+ * if invalid options are encountered.
  *
  */
 public interface Index

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/schema/IndexMetadata.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/IndexMetadata.java b/src/java/org/apache/cassandra/schema/IndexMetadata.java
index ee9179a..7c60a64 100644
--- a/src/java/org/apache/cassandra/schema/IndexMetadata.java
+++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java
@@ -138,7 +138,7 @@ public final class IndexMetadata
             return (cfName + "_" + root + "_idx").replaceAll("\\W", "");
     }
 
-    public void validate()
+    public void validate(CFMetaData cfm)
     {
         if (!isNameValid(name))
             throw new ConfigurationException("Illegal index name " + name);
@@ -155,11 +155,14 @@ public final class IndexMetadata
             Class<Index> indexerClass = FBUtilities.classForName(className, "custom indexer");
             if(!Index.class.isAssignableFrom(indexerClass))
                 throw new ConfigurationException(String.format("Specified Indexer class (%s) does not implement the Indexer interface", className));
-            validateCustomIndexOptions(indexerClass, options);
+            validateCustomIndexOptions(cfm, indexerClass, options);
         }
     }
 
-    private void validateCustomIndexOptions(Class<? extends Index> indexerClass, Map<String, String> options) throws ConfigurationException
+    private void validateCustomIndexOptions(CFMetaData cfm,
+                                            Class<? extends Index> indexerClass,
+                                            Map<String, String> options)
+    throws ConfigurationException
     {
         try
         {
@@ -169,7 +172,16 @@ public final class IndexMetadata
             if (filteredOptions.isEmpty())
                 return;
 
-            Map<?,?> unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class).invoke(null, filteredOptions);
+            Map<?,?> unknownOptions;
+            try
+            {
+                unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class, CFMetaData.class).invoke(null, filteredOptions, cfm);
+            }
+            catch (NoSuchMethodException e)
+            {
+                unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class).invoke(null, filteredOptions);
+            }
+
             if (!unknownOptions.isEmpty())
                 throw new ConfigurationException(String.format("Properties specified %s are not understood by %s", unknownOptions.keySet(), indexerClass.getSimpleName()));
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/test/unit/org/apache/cassandra/index/CustomIndexTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/index/CustomIndexTest.java b/test/unit/org/apache/cassandra/index/CustomIndexTest.java
index b305868..3bfb6a5 100644
--- a/test/unit/org/apache/cassandra/index/CustomIndexTest.java
+++ b/test/unit/org/apache/cassandra/index/CustomIndexTest.java
@@ -32,6 +32,7 @@ import org.apache.cassandra.utils.FBUtilities;
 import static org.apache.cassandra.Util.throwAssert;
 import static org.apache.cassandra.cql3.statements.IndexTarget.CUSTOM_INDEX_OPTION_NAME;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -504,6 +505,28 @@ public class CustomIndexTest extends CQLTester
             assertEquals(index.rowsDeleted.get(i).clustering(), index.rowsInserted.get(i).clustering());
     }
 
+    @Test
+    public void validateOptions() throws Throwable
+    {
+        createTable("CREATE TABLE %s(k int, c int, v1 int, v2 int, PRIMARY KEY(k,c))");
+        createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c, v2) USING '%s' WITH OPTIONS = {'foo':'bar'}",
+                                  IndexWithValidateOptions.class.getName()));
+        assertNotNull(IndexWithValidateOptions.options);
+        assertEquals("bar", IndexWithValidateOptions.options.get("foo"));
+    }
+
+    @Test
+    public void validateOptionsWithCFMetaData() throws Throwable
+    {
+        createTable("CREATE TABLE %s(k int, c int, v1 int, v2 int, PRIMARY KEY(k,c))");
+        createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c, v2) USING '%s' WITH OPTIONS = {'foo':'bar'}",
+                                  IndexWithOverloadedValidateOptions.class.getName()));
+        CFMetaData cfm = getCurrentColumnFamilyStore().metadata;
+        assertEquals(cfm, IndexWithOverloadedValidateOptions.cfm);
+        assertNotNull(IndexWithOverloadedValidateOptions.options);
+        assertEquals("bar", IndexWithOverloadedValidateOptions.options.get("foo"));
+    }
+
     private void testCreateIndex(String indexName, String... targetColumnNames) throws Throwable
     {
         createIndex(String.format("CREATE CUSTOM INDEX %s ON %%s(%s) USING '%s'",
@@ -672,4 +695,38 @@ public class CustomIndexTest extends CQLTester
             throw new InvalidRequestException("None shall pass");
         }
     }
+
+    public static final class IndexWithValidateOptions extends StubIndex
+    {
+        public static Map<String, String> options;
+
+        public IndexWithValidateOptions(ColumnFamilyStore baseCfs, IndexMetadata metadata)
+        {
+            super(baseCfs, metadata);
+        }
+
+        public static Map<String, String> validateOptions(Map<String, String> options)
+        {
+            IndexWithValidateOptions.options = options;
+            return new HashMap<>();
+        }
+    }
+
+    public static final class IndexWithOverloadedValidateOptions extends StubIndex
+    {
+        public static CFMetaData cfm;
+        public static Map<String, String> options;
+
+        public IndexWithOverloadedValidateOptions(ColumnFamilyStore baseCfs, IndexMetadata metadata)
+        {
+            super(baseCfs, metadata);
+        }
+
+        public static Map<String, String> validateOptions(Map<String, String> options, CFMetaData cfm)
+        {
+            IndexWithOverloadedValidateOptions.options = options;
+            IndexWithOverloadedValidateOptions.cfm = cfm;
+            return new HashMap<>();
+        }
+    }
 }


[5/6] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.3

Posted by sa...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.3


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/501f75bf
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/501f75bf
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/501f75bf

Branch: refs/heads/cassandra-3.3
Commit: 501f75bf99b62f94839de995a8e778aabb500523
Parents: b48d71c 5e5ea772
Author: Sam Tunnicliffe <sa...@beobal.com>
Authored: Fri Jan 15 11:29:22 2016 +0000
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Fri Jan 15 11:29:22 2016 +0000

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../org/apache/cassandra/config/CFMetaData.java |  2 +-
 src/java/org/apache/cassandra/index/Index.java  | 21 +++++---
 .../apache/cassandra/schema/IndexMetadata.java  | 20 +++++--
 .../apache/cassandra/index/CustomIndexTest.java | 57 ++++++++++++++++++++
 5 files changed, 88 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 9bc1349,ff607a5..991077d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,9 -1,6 +1,10 @@@
 -3.0.3
 +3.3
 + * Avoid bootstrap hanging when existing nodes have no data to stream (CASSANDRA-11010)
 +Merged from 3.0:
+  * Support passing base table metadata to custom 2i validation (CASSANDRA-10924)
   * Ensure stale index entries are purged during reads (CASSANDRA-11013)
 + * (cqlsh) Also apply --connect-timeout to control connection
 +   timeout (CASSANDRA-10959)
   * Fix AssertionError when removing from list using UPDATE (CASSANDRA-10954)
   * Fix UnsupportedOperationException when reading old sstable with range
     tombstone (CASSANDRA-10743)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/src/java/org/apache/cassandra/index/Index.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/src/java/org/apache/cassandra/schema/IndexMetadata.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/schema/IndexMetadata.java
index 59ac1cf,7c60a64..04e06ab
--- a/src/java/org/apache/cassandra/schema/IndexMetadata.java
+++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java
@@@ -138,12 -133,12 +138,12 @@@ public final class IndexMetadat
      public static String getDefaultIndexName(String cfName, String root)
      {
          if (root == null)
 -            return (cfName + "_" + "idx").replaceAll("\\W", "");
 +            return PATTERN_NON_WORD_CHAR.matcher(cfName + "_" + "idx").replaceAll("");
          else
 -            return (cfName + "_" + root + "_idx").replaceAll("\\W", "");
 +            return PATTERN_NON_WORD_CHAR.matcher(cfName + "_" + root + "_idx").replaceAll("");
      }
  
-     public void validate()
+     public void validate(CFMetaData cfm)
      {
          if (!isNameValid(name))
              throw new ConfigurationException("Illegal index name " + name);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/501f75bf/test/unit/org/apache/cassandra/index/CustomIndexTest.java
----------------------------------------------------------------------


[2/6] cassandra git commit: Add custom 2i validation method which uses base CFMetaData

Posted by sa...@apache.org.
Add custom 2i validation method which uses base CFMetaData

Patch by Andrés de la Peña; reviewed by Sam Tunnicliffe for
CASSANDRA-10924


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5e5ea772
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5e5ea772
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5e5ea772

Branch: refs/heads/cassandra-3.3
Commit: 5e5ea772ed346b5197a6a7be3046953686a8975a
Parents: 97e8953
Author: Andrés de la Peña <ad...@stratio.com>
Authored: Tue Jan 12 15:11:37 2016 +0000
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Fri Jan 15 11:13:19 2016 +0000

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../org/apache/cassandra/config/CFMetaData.java |  2 +-
 src/java/org/apache/cassandra/index/Index.java  | 21 +++++---
 .../apache/cassandra/schema/IndexMetadata.java  | 20 +++++--
 .../apache/cassandra/index/CustomIndexTest.java | 57 ++++++++++++++++++++
 5 files changed, 88 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 8c3527f..ff607a5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.3
+ * Support passing base table metadata to custom 2i validation (CASSANDRA-10924)
  * Ensure stale index entries are purged during reads (CASSANDRA-11013)
  * Fix AssertionError when removing from list using UPDATE (CASSANDRA-10954)
  * Fix UnsupportedOperationException when reading old sstable with range

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java
index 62b2369..cb6d3b8 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -877,7 +877,7 @@ public final class CFMetaData
                 throw new ConfigurationException("Duplicate index name " + index.name);
             indexNames.add(index.name);
 
-            index.validate();
+            index.validate(this);
         }
 
         return this;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/index/Index.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/index/Index.java b/src/java/org/apache/cassandra/index/Index.java
index 084d0e3..71dcfc9 100644
--- a/src/java/org/apache/cassandra/index/Index.java
+++ b/src/java/org/apache/cassandra/index/Index.java
@@ -89,16 +89,21 @@ import org.apache.cassandra.utils.concurrent.OpOrder;
  * The post processing function is obtained from the Index's postProcessorFor method; the built-in indexes which ship
  * with Cassandra return a no-op function here.
  *
- * An optional static method may be provided to validate custom index options:
+ * An optional static method may be provided to validate custom index options (two variants are supported):
  *
- * <pre> {@code
- * public static Map<String, String> validateOptions(Map<String, String> options);
- * } </pre>
+ * <pre>{@code public static Map<String, String> validateOptions(Map<String, String> options);</pre>
  *
- * The input is the map of index options supplied in the WITH clause of a CREATE INDEX statement. The method should
- * return a map containing any of the supplied options which are not valid for the implementation. If the returned
- * map is not empty, validation is considered failed and an error is raised. Alternatively, the implementation may
- * choose to throw an org.apache.cassandra.exceptions.ConfigurationException if invalid options are encountered.
+ * The input is the map of index options supplied in the WITH clause of a CREATE INDEX statement.
+ *
+ * <pre>{@code public static Map<String, String> validateOptions(Map<String, String> options, CFMetaData cfm);}</pre>
+ *
+ * In this version, the base table's metadata is also supplied as an argument.
+ * If both overloaded methods are provided, only the one including the base table's metadata will be invoked.
+ *
+ * The validation method should return a map containing any of the supplied options which are not valid for the
+ * implementation. If the returned map is not empty, validation is considered failed and an error is raised.
+ * Alternatively, the implementation may choose to throw an org.apache.cassandra.exceptions.ConfigurationException
+ * if invalid options are encountered.
  *
  */
 public interface Index

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/src/java/org/apache/cassandra/schema/IndexMetadata.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/IndexMetadata.java b/src/java/org/apache/cassandra/schema/IndexMetadata.java
index ee9179a..7c60a64 100644
--- a/src/java/org/apache/cassandra/schema/IndexMetadata.java
+++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java
@@ -138,7 +138,7 @@ public final class IndexMetadata
             return (cfName + "_" + root + "_idx").replaceAll("\\W", "");
     }
 
-    public void validate()
+    public void validate(CFMetaData cfm)
     {
         if (!isNameValid(name))
             throw new ConfigurationException("Illegal index name " + name);
@@ -155,11 +155,14 @@ public final class IndexMetadata
             Class<Index> indexerClass = FBUtilities.classForName(className, "custom indexer");
             if(!Index.class.isAssignableFrom(indexerClass))
                 throw new ConfigurationException(String.format("Specified Indexer class (%s) does not implement the Indexer interface", className));
-            validateCustomIndexOptions(indexerClass, options);
+            validateCustomIndexOptions(cfm, indexerClass, options);
         }
     }
 
-    private void validateCustomIndexOptions(Class<? extends Index> indexerClass, Map<String, String> options) throws ConfigurationException
+    private void validateCustomIndexOptions(CFMetaData cfm,
+                                            Class<? extends Index> indexerClass,
+                                            Map<String, String> options)
+    throws ConfigurationException
     {
         try
         {
@@ -169,7 +172,16 @@ public final class IndexMetadata
             if (filteredOptions.isEmpty())
                 return;
 
-            Map<?,?> unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class).invoke(null, filteredOptions);
+            Map<?,?> unknownOptions;
+            try
+            {
+                unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class, CFMetaData.class).invoke(null, filteredOptions, cfm);
+            }
+            catch (NoSuchMethodException e)
+            {
+                unknownOptions = (Map) indexerClass.getMethod("validateOptions", Map.class).invoke(null, filteredOptions);
+            }
+
             if (!unknownOptions.isEmpty())
                 throw new ConfigurationException(String.format("Properties specified %s are not understood by %s", unknownOptions.keySet(), indexerClass.getSimpleName()));
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e5ea772/test/unit/org/apache/cassandra/index/CustomIndexTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/index/CustomIndexTest.java b/test/unit/org/apache/cassandra/index/CustomIndexTest.java
index b305868..3bfb6a5 100644
--- a/test/unit/org/apache/cassandra/index/CustomIndexTest.java
+++ b/test/unit/org/apache/cassandra/index/CustomIndexTest.java
@@ -32,6 +32,7 @@ import org.apache.cassandra.utils.FBUtilities;
 import static org.apache.cassandra.Util.throwAssert;
 import static org.apache.cassandra.cql3.statements.IndexTarget.CUSTOM_INDEX_OPTION_NAME;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -504,6 +505,28 @@ public class CustomIndexTest extends CQLTester
             assertEquals(index.rowsDeleted.get(i).clustering(), index.rowsInserted.get(i).clustering());
     }
 
+    @Test
+    public void validateOptions() throws Throwable
+    {
+        createTable("CREATE TABLE %s(k int, c int, v1 int, v2 int, PRIMARY KEY(k,c))");
+        createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c, v2) USING '%s' WITH OPTIONS = {'foo':'bar'}",
+                                  IndexWithValidateOptions.class.getName()));
+        assertNotNull(IndexWithValidateOptions.options);
+        assertEquals("bar", IndexWithValidateOptions.options.get("foo"));
+    }
+
+    @Test
+    public void validateOptionsWithCFMetaData() throws Throwable
+    {
+        createTable("CREATE TABLE %s(k int, c int, v1 int, v2 int, PRIMARY KEY(k,c))");
+        createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c, v2) USING '%s' WITH OPTIONS = {'foo':'bar'}",
+                                  IndexWithOverloadedValidateOptions.class.getName()));
+        CFMetaData cfm = getCurrentColumnFamilyStore().metadata;
+        assertEquals(cfm, IndexWithOverloadedValidateOptions.cfm);
+        assertNotNull(IndexWithOverloadedValidateOptions.options);
+        assertEquals("bar", IndexWithOverloadedValidateOptions.options.get("foo"));
+    }
+
     private void testCreateIndex(String indexName, String... targetColumnNames) throws Throwable
     {
         createIndex(String.format("CREATE CUSTOM INDEX %s ON %%s(%s) USING '%s'",
@@ -672,4 +695,38 @@ public class CustomIndexTest extends CQLTester
             throw new InvalidRequestException("None shall pass");
         }
     }
+
+    public static final class IndexWithValidateOptions extends StubIndex
+    {
+        public static Map<String, String> options;
+
+        public IndexWithValidateOptions(ColumnFamilyStore baseCfs, IndexMetadata metadata)
+        {
+            super(baseCfs, metadata);
+        }
+
+        public static Map<String, String> validateOptions(Map<String, String> options)
+        {
+            IndexWithValidateOptions.options = options;
+            return new HashMap<>();
+        }
+    }
+
+    public static final class IndexWithOverloadedValidateOptions extends StubIndex
+    {
+        public static CFMetaData cfm;
+        public static Map<String, String> options;
+
+        public IndexWithOverloadedValidateOptions(ColumnFamilyStore baseCfs, IndexMetadata metadata)
+        {
+            super(baseCfs, metadata);
+        }
+
+        public static Map<String, String> validateOptions(Map<String, String> options, CFMetaData cfm)
+        {
+            IndexWithOverloadedValidateOptions.options = options;
+            IndexWithOverloadedValidateOptions.cfm = cfm;
+            return new HashMap<>();
+        }
+    }
 }