ACCUMULO-802 added iterators and constraints for namespaces. Currently the constraint part of the test fails, but iterators work.
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/fa67f350 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/fa67f350 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/fa67f350 Branch: refs/heads/ACCUMULO-802 Commit: fa67f3500865a4ca91034c393aa3ef5601899073 Parents: 7fc1ff3 Author: Sean Hickey <[email protected]> Authored: Tue Jul 23 16:25:15 2013 -0400 Committer: Christopher Tubbs <[email protected]> Committed: Thu Oct 31 21:25:04 2013 -0400 ---------------------------------------------------------------------- .../client/admin/TableNamespaceOperations.java | 186 +++++++++++++++-- .../admin/TableNamespaceOperationsHelper.java | 206 +++++++++++++++++++ .../admin/TableNamespaceOperationsImpl.java | 2 +- .../mock/MockTableNamespaceOperations.java | 4 +- .../accumulo/test/TableNamespacesTest.java | 89 +++++++- 5 files changed, 466 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/fa67f350/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java index 9658dc6..f572104 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java +++ b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java @@ -16,6 +16,7 @@ */ package org.apache.accumulo.core.client.admin; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -24,9 +25,11 @@ import java.util.SortedSet; import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.IteratorSetting; import org.apache.accumulo.core.client.TableNamespaceExistsException; import org.apache.accumulo.core.client.TableNamespaceNotEmptyException; import org.apache.accumulo.core.client.TableNamespaceNotFoundException; +import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope; /** * Provides a class for administering table namespaces @@ -93,7 +96,8 @@ public interface TableNamespaceOperations { * @throws TableNamespaceExistsException * if the table namespace already exists */ - public void create(String namespace, boolean versioningIter, TimeType timeType) throws AccumuloException, AccumuloSecurityException, TableNamespaceExistsException; + public void create(String namespace, boolean versioningIter, TimeType timeType) throws AccumuloException, AccumuloSecurityException, + TableNamespaceExistsException; /** * Delete a table namespace if it is empty @@ -106,7 +110,7 @@ public interface TableNamespaceOperations { * if the user does not have permission * @throws TableNamespaceNotFoundException * if the table namespace does not exist - * @throws TableNamespaceNotEmptyException + * @throws TableNamespaceNotEmptyException * if the table namespaces still contains tables */ public void delete(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException, TableNamespaceNotEmptyException; @@ -124,10 +128,11 @@ public interface TableNamespaceOperations { * if the user does not have permission * @throws TableNamespaceNotFoundException * if the table namespace does not exist - * @throws TableNamespaceNotEmptyException + * @throws TableNamespaceNotEmptyException * if the table namespaces still contains tables */ - public void delete(String namespace, boolean deleteTables) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException, TableNamespaceNotEmptyException; + public void delete(String namespace, boolean deleteTables) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException, + TableNamespaceNotEmptyException; /** * Rename a table namespace @@ -147,7 +152,7 @@ public interface TableNamespaceOperations { */ public void rename(String oldNamespaceName, String newNamespaceName) throws AccumuloSecurityException, TableNamespaceNotFoundException, AccumuloException, TableNamespaceExistsException; - + /** * Sets a property on a table namespace. Note that it may take a short period of time (a second) to propagate the change everywhere. * @@ -165,7 +170,7 @@ public interface TableNamespaceOperations { public void setProperty(String namespace, String property, String value) throws AccumuloException, AccumuloSecurityException; /** - * Removes a property from a table namespace. Note that it may take a short period of time (a second) to propagate the change everywhere. + * Removes a property from a table namespace. Note that it may take a short period of time (a second) to propagate the change everywhere. * * @param namespace * the name of the table namespace @@ -179,12 +184,11 @@ public interface TableNamespaceOperations { public void removeProperty(String namespace, String property) throws AccumuloException, AccumuloSecurityException; /** - * Gets properties of a table namespace. Note that recently changed properties may not be available immediately. + * Gets properties of a table namespace. Note that recently changed properties may not be available immediately. * * @param namespace * the name of the table namespace - * @return all properties visible by this table (system and per-table properties). Note that recently changed - * properties may not be visible immediately. + * @return all properties visible by this table (system and per-table properties). Note that recently changed properties may not be visible immediately. * @throws TableNamespaceNotFoundException * if the table does not exist */ @@ -220,21 +224,20 @@ public interface TableNamespaceOperations { * @return the map from table namespace name to internal table namespace id */ public Map<String,String> namespaceIdMap(); - + /** * Gets the number of bytes being used in the files for the set of tables in this namespace - * + * * @param namespace * the table namespace to get the set of tables from - * - * @return a list of disk usage objects containing linked table names and sizes + * + * @return a list of disk usage objects containing linked table names and sizes * @throws AccumuloException * when there is a general accumulo error * @throws AccumuloSecurityException * when the user does not have the proper permissions */ public List<DiskUsage> getDiskUsage(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException; - /** * Clone a all the tables in a table namespace to a new table namespace. Optionally copy all their properties as well. @@ -254,12 +257,161 @@ public interface TableNamespaceOperations { * @throws AccumuloSecurityException * when the user does not have the proper permissions * @throws AccumuloException - * when there is a general accumulo error + * when there is a general accumulo error * @throws TableNamespaceNotFoundException - * If the old table namespace doesn't exist + * If the old table namespace doesn't exist * @throws TableNamespaceExistsException - * If the new table namespace already exists + * If the new table namespace already exists */ public void clone(String srcName, String newName, boolean flush, Map<String,String> propertiesToSet, Set<String> propertiesToExclude, Boolean copyTableProps) throws AccumuloSecurityException, AccumuloException, TableNamespaceNotFoundException, TableNamespaceExistsException; + + /** + * Add an iterator to a table namespace on all scopes. + * + * @param tableNamespace + * the name of the table namespace + * @param setting + * object specifying the properties of the iterator + * @throws AccumuloSecurityException + * thrown if the user does not have the ability to set properties on the table + * @throws AccumuloException + * @throws TableNamespaceNotFoundException + * throw if the table namespace no longer exists + * @throws IllegalArgumentException + * if the setting conflicts with any existing iterators + */ + public void attachIterator(String tableNamespace, IteratorSetting setting) throws AccumuloSecurityException, AccumuloException, + TableNamespaceNotFoundException; + + /** + * Add an iterator to a table namespace on the given scopes. + * + * @param tableNamespace + * the name of the table namespace + * @param setting + * object specifying the properties of the iterator + * @throws AccumuloSecurityException + * thrown if the user does not have the ability to set properties on the table namespace + * @throws AccumuloException + * @throws TableNamespaceNotFoundException + * throw if the table namespace no longer exists + * @throws IllegalArgumentException + * if the setting conflicts with any existing iterators + */ + public void attachIterator(String tableNamespace, IteratorSetting setting, EnumSet<IteratorScope> scopes) throws AccumuloSecurityException, + AccumuloException, TableNamespaceNotFoundException; + + /** + * Remove an iterator from a table namespace by name. + * + * @param tableNamespace + * the name of the table namespace + * @param name + * the name of the iterator + * @param scopes + * the scopes of the iterator + * @throws AccumuloSecurityException + * thrown if the user does not have the ability to set properties on the table namespace + * @throws AccumuloException + * @throws TableNamespaceNotFoundException + * thrown if the table namespace no longer exists + */ + public void removeIterator(String tableNamespace, String name, EnumSet<IteratorScope> scopes) throws AccumuloSecurityException, AccumuloException, + TableNamespaceNotFoundException; + + /** + * Get the settings for an iterator. + * + * @param tableNamespace + * the name of the table namespace + * @param name + * the name of the iterator + * @param scope + * the scope of the iterator + * @return the settings for this iterator + * @throws AccumuloSecurityException + * thrown if the user does not have the ability to set properties on the table namespace + * @throws AccumuloException + * @throws TableNamespaceNotFoundException + * thrown if the table namespace no longer exists + */ + public IteratorSetting getIteratorSetting(String tableNamespace, String name, IteratorScope scope) throws AccumuloSecurityException, AccumuloException, + NumberFormatException, TableNamespaceNotFoundException; + + /** + * Get a list of iterators for this table namespace. + * + * @param tableNamespace + * the name of the table namespace + * @return a set of iterator names + * @throws AccumuloSecurityException + * thrown if the user does not have the ability to set properties on the table namespace + * @throws AccumuloException + * @throws TableNamespaceNotFoundException + * thrown if the table namespace no longer exists + */ + public Map<String,EnumSet<IteratorScope>> listIterators(String tableNamespace) throws AccumuloSecurityException, AccumuloException, + TableNamespaceNotFoundException; + + /** + * Check whether a given iterator configuration conflicts with existing configuration; in particular, determine if the name or priority are already in use for + * the specified scopes. + * + * @param tableNamespace + * the name of the table namespace + * @param setting + * object specifying the properties of the iterator + * @throws AccumuloException + * @throws TableNamespaceNotFoundException + * thrown if the table namespace no longer exists + * @throws IllegalStateException + * if the setting conflicts with any existing iterators + */ + public void checkIteratorConflicts(String tableNamespace, IteratorSetting setting, EnumSet<IteratorScope> scopes) throws AccumuloException, + TableNamespaceNotFoundException; + + /** + * Add a new constraint to a table namespace. + * + * @param tableNamespace + * the name of the table namespace + * @param constraintClassName + * the full name of the constraint class + * @return the unique number assigned to the constraint + * @throws AccumuloException + * thrown if the constraint has already been added to the table or if there are errors in the configuration of existing constraints + * @throws AccumuloSecurityException + * thrown if the user doesn't have permission to add the constraint + * @throws TableNamespaceNotFoundException + * thrown if the table namespace no longer exists + */ + public int addConstraint(String tableNamespace, String constraintClassName) throws AccumuloException, AccumuloSecurityException, + TableNamespaceNotFoundException; + + /** + * Remove a constraint from a table namespace. + * + * @param tableNamespace + * the name of the table namespace + * @param number + * the unique number assigned to the constraint + * @throws AccumuloException + * @throws AccumuloSecurityException + * thrown if the user doesn't have permission to remove the constraint + */ + public void removeConstraint(String tableNamespace, int number) throws AccumuloException, AccumuloSecurityException; + + /** + * List constraints on a table namespace with their assigned numbers. + * + * @param tableNamespace + * the name of the table namespace + * @return a map from constraint class name to assigned number + * @throws AccumuloException + * thrown if there are errors in the configuration of existing constraints + * @throws TableNamespaceNotFoundException + * thrown if the table namespace no longer exists + */ + public Map<String,Integer> listConstraints(String tableNamespace) throws AccumuloException, TableNamespaceNotFoundException; } http://git-wip-us.apache.org/repos/asf/accumulo/blob/fa67f350/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsHelper.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsHelper.java b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsHelper.java new file mode 100644 index 0000000..c60c9ba --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsHelper.java @@ -0,0 +1,206 @@ +/* + * 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.accumulo.core.client.admin; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.IteratorSetting; +import org.apache.accumulo.core.client.TableNamespaceNotFoundException; +import org.apache.accumulo.core.conf.Property; +import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope; + +public abstract class TableNamespaceOperationsHelper implements TableNamespaceOperations { + + @Override + public void attachIterator(String tableNamespace, IteratorSetting setting) throws AccumuloSecurityException, AccumuloException, + TableNamespaceNotFoundException { + attachIterator(tableNamespace, setting, EnumSet.allOf(IteratorScope.class)); + } + + @Override + public void attachIterator(String tableNamespace, IteratorSetting setting, EnumSet<IteratorScope> scopes) throws AccumuloSecurityException, + AccumuloException, TableNamespaceNotFoundException { + checkIteratorConflicts(tableNamespace, setting, scopes); + for (IteratorScope scope : scopes) { + String root = String.format("%s%s.%s", Property.TABLE_ITERATOR_PREFIX, scope.name().toLowerCase(), setting.getName()); + for (Entry<String,String> prop : setting.getOptions().entrySet()) { + this.setProperty(tableNamespace, root + ".opt." + prop.getKey(), prop.getValue()); + } + this.setProperty(tableNamespace, root, setting.getPriority() + "," + setting.getIteratorClass()); + } + } + + @Override + public void removeIterator(String tableNamespace, String name, EnumSet<IteratorScope> scopes) throws AccumuloSecurityException, AccumuloException, + TableNamespaceNotFoundException { + if (!exists(tableNamespace)) + throw new TableNamespaceNotFoundException(null, tableNamespace, null); + Map<String,String> copy = new TreeMap<String,String>(); + for (Entry<String,String> property : this.getProperties(tableNamespace)) { + copy.put(property.getKey(), property.getValue()); + } + for (IteratorScope scope : scopes) { + String root = String.format("%s%s.%s", Property.TABLE_ITERATOR_PREFIX, scope.name().toLowerCase(), name); + for (Entry<String,String> property : copy.entrySet()) { + if (property.getKey().equals(root) || property.getKey().startsWith(root + ".opt.")) + this.removeProperty(tableNamespace, property.getKey()); + } + } + } + + @Override + public IteratorSetting getIteratorSetting(String tableNamespace, String name, IteratorScope scope) throws AccumuloSecurityException, AccumuloException, + TableNamespaceNotFoundException { + if (!exists(tableNamespace)) + throw new TableNamespaceNotFoundException(null, tableNamespace, null); + int priority = -1; + String classname = null; + Map<String,String> settings = new HashMap<String,String>(); + + String root = String.format("%s%s.%s", Property.TABLE_ITERATOR_PREFIX, scope.name().toLowerCase(), name); + String opt = root + ".opt."; + for (Entry<String,String> property : this.getProperties(tableNamespace)) { + if (property.getKey().equals(root)) { + String parts[] = property.getValue().split(","); + if (parts.length != 2) { + throw new AccumuloException("Bad value for iterator setting: " + property.getValue()); + } + priority = Integer.parseInt(parts[0]); + classname = parts[1]; + } else if (property.getKey().startsWith(opt)) { + settings.put(property.getKey().substring(opt.length()), property.getValue()); + } + } + if (priority <= 0 || classname == null) { + return null; + } + return new IteratorSetting(priority, name, classname, settings); + } + + @Override + public Map<String,EnumSet<IteratorScope>> listIterators(String tableNamespace) throws AccumuloSecurityException, AccumuloException, + TableNamespaceNotFoundException { + if (!exists(tableNamespace)) + throw new TableNamespaceNotFoundException(null, tableNamespace, null); + Map<String,EnumSet<IteratorScope>> result = new TreeMap<String,EnumSet<IteratorScope>>(); + for (Entry<String,String> property : this.getProperties(tableNamespace)) { + String name = property.getKey(); + String[] parts = name.split("\\."); + if (parts.length == 4) { + if (parts[0].equals("table") && parts[1].equals("iterator")) { + IteratorScope scope = IteratorScope.valueOf(parts[2]); + if (!result.containsKey(parts[3])) + result.put(parts[3], EnumSet.noneOf(IteratorScope.class)); + result.get(parts[3]).add(scope); + } + } + } + return result; + } + + @Override + public void checkIteratorConflicts(String tableNamespace, IteratorSetting setting, EnumSet<IteratorScope> scopes) throws AccumuloException, + TableNamespaceNotFoundException { + if (!exists(tableNamespace)) + throw new TableNamespaceNotFoundException(null, tableNamespace, null); + for (IteratorScope scope : scopes) { + String scopeStr = String.format("%s%s", Property.TABLE_ITERATOR_PREFIX, scope.name().toLowerCase()); + String nameStr = String.format("%s.%s", scopeStr, setting.getName()); + String optStr = String.format("%s.opt.", nameStr); + Map<String,String> optionConflicts = new TreeMap<String,String>(); + for (Entry<String,String> property : this.getProperties(tableNamespace)) { + if (property.getKey().startsWith(scopeStr)) { + if (property.getKey().equals(nameStr)) + throw new AccumuloException(new IllegalArgumentException("iterator name conflict for " + setting.getName() + ": " + property.getKey() + "=" + + property.getValue())); + if (property.getKey().startsWith(optStr)) + optionConflicts.put(property.getKey(), property.getValue()); + if (property.getKey().contains(".opt.")) + continue; + String parts[] = property.getValue().split(","); + if (parts.length != 2) + throw new AccumuloException("Bad value for existing iterator setting: " + property.getKey() + "=" + property.getValue()); + try { + if (Integer.parseInt(parts[0]) == setting.getPriority()) + throw new AccumuloException(new IllegalArgumentException("iterator priority conflict: " + property.getKey() + "=" + property.getValue())); + } catch (NumberFormatException e) { + throw new AccumuloException("Bad value for existing iterator setting: " + property.getKey() + "=" + property.getValue()); + } + } + } + if (optionConflicts.size() > 0) + throw new AccumuloException(new IllegalArgumentException("iterator options conflict for " + setting.getName() + ": " + optionConflicts)); + } + } + + @Override + public int addConstraint(String tableNamespace, String constraintClassName) throws AccumuloException, AccumuloSecurityException, + TableNamespaceNotFoundException { + TreeSet<Integer> constraintNumbers = new TreeSet<Integer>(); + TreeMap<String,Integer> constraintClasses = new TreeMap<String,Integer>(); + int i; + for (Entry<String,String> property : this.getProperties(tableNamespace)) { + if (property.getKey().startsWith(Property.TABLE_CONSTRAINT_PREFIX.toString())) { + try { + i = Integer.parseInt(property.getKey().substring(Property.TABLE_CONSTRAINT_PREFIX.toString().length())); + } catch (NumberFormatException e) { + throw new AccumuloException("Bad key for existing constraint: " + property.toString()); + } + constraintNumbers.add(i); + constraintClasses.put(property.getValue(), i); + } + } + i = 1; + while (constraintNumbers.contains(i)) + i++; + if (constraintClasses.containsKey(constraintClassName)) + throw new AccumuloException("Constraint " + constraintClassName + " already exists for table " + tableNamespace + " with number " + + constraintClasses.get(constraintClassName)); + this.setProperty(tableNamespace, Property.TABLE_CONSTRAINT_PREFIX.toString() + i, constraintClassName); + return i; + } + + @Override + public void removeConstraint(String tableNamespace, int number) throws AccumuloException, AccumuloSecurityException { + this.removeProperty(tableNamespace, Property.TABLE_CONSTRAINT_PREFIX.toString() + number); + } + + @Override + public Map<String,Integer> listConstraints(String tableNamespace) throws AccumuloException, TableNamespaceNotFoundException { + Map<String,Integer> constraints = new TreeMap<String,Integer>(); + for (Entry<String,String> property : this.getProperties(tableNamespace)) { + if (property.getKey().startsWith(Property.TABLE_CONSTRAINT_PREFIX.toString())) { + if (constraints.containsKey(property.getValue())) + throw new AccumuloException("Same constraint configured twice: " + property.getKey() + "=" + Property.TABLE_CONSTRAINT_PREFIX + + constraints.get(property.getValue()) + "=" + property.getKey()); + try { + constraints.put(property.getValue(), Integer.parseInt(property.getKey().substring(Property.TABLE_CONSTRAINT_PREFIX.toString().length()))); + } catch (NumberFormatException e) { + throw new AccumuloException("Bad key for existing constraint: " + property.toString()); + } + } + } + return constraints; + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/fa67f350/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java index 7df73f9..0d54b51 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java @@ -67,7 +67,7 @@ import org.apache.thrift.transport.TTransportException; * Provides a class for administering table namespaces * */ -public class TableNamespaceOperationsImpl implements TableNamespaceOperations { +public class TableNamespaceOperationsImpl extends TableNamespaceOperationsHelper { private Instance instance; private Credentials credentials; http://git-wip-us.apache.org/repos/asf/accumulo/blob/fa67f350/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespaceOperations.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespaceOperations.java b/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespaceOperations.java index 358a980..1364f0f 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespaceOperations.java +++ b/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespaceOperations.java @@ -33,12 +33,12 @@ import org.apache.accumulo.core.client.TableNamespaceNotEmptyException; import org.apache.accumulo.core.client.TableNamespaceNotFoundException; import org.apache.accumulo.core.client.TableNotFoundException; import org.apache.accumulo.core.client.admin.DiskUsage; -import org.apache.accumulo.core.client.admin.TableNamespaceOperations; +import org.apache.accumulo.core.client.admin.TableNamespaceOperationsHelper; import org.apache.accumulo.core.client.admin.TimeType; import org.apache.accumulo.core.client.impl.Tables; import org.apache.commons.lang.NotImplementedException; -public class MockTableNamespaceOperations implements TableNamespaceOperations { +public class MockTableNamespaceOperations extends TableNamespaceOperationsHelper { final private MockAccumulo acu; final private String username; http://git-wip-us.apache.org/repos/asf/accumulo/blob/fa67f350/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java ---------------------------------------------------------------------- diff --git a/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java b/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java index 6527b13..cfd8000 100644 --- a/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java +++ b/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java @@ -20,21 +20,35 @@ package org.apache.accumulo.test; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Random; import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.BatchWriter; +import org.apache.accumulo.core.client.BatchWriterConfig; import org.apache.accumulo.core.client.Connector; import org.apache.accumulo.core.client.Instance; +import org.apache.accumulo.core.client.IteratorSetting; +import org.apache.accumulo.core.client.MutationsRejectedException; +import org.apache.accumulo.core.client.Scanner; import org.apache.accumulo.core.client.TableNamespaceNotEmptyException; import org.apache.accumulo.core.client.TableNamespaceNotFoundException; import org.apache.accumulo.core.client.TableNotFoundException; import org.apache.accumulo.core.client.impl.TableNamespaces; import org.apache.accumulo.core.client.impl.Tables; import org.apache.accumulo.core.conf.Property; +import org.apache.accumulo.core.data.Key; +import org.apache.accumulo.core.data.Mutation; +import org.apache.accumulo.core.data.Value; +import org.apache.accumulo.core.iterators.Filter; +import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope; +import org.apache.accumulo.core.security.Authorizations; +import org.apache.accumulo.examples.simple.constraints.NumericValueConstraint; import org.apache.accumulo.minicluster.MiniAccumuloCluster; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -155,7 +169,7 @@ public class TableNamespacesTest { assertTrue(checkTableHasProp(c, tableName1, propKey, propVal)); // test a second table to be sure the first wasn't magical - // (also, changed the order, the namespace already exists with the property) + // (also, changed the order, the namespace has the property already) c.tableOperations().create(tableName2); assertTrue(checkTableHasProp(c, tableName2, propKey, propVal)); @@ -176,6 +190,24 @@ public class TableNamespacesTest { c.tableNamespaceOperations().setProperty(Constants.DEFAULT_TABLE_NAMESPACE, propKey, propVal); assertTrue(checkTableHasProp(c, tableName, propKey, propVal)); + + // test the properties server-side by configuring an iterator. + // should not show anything with column-family = 'a' + String tableName3 = namespace + ".table3"; + c.tableOperations().create(tableName3); + + IteratorSetting setting = new IteratorSetting(250, "thing", SimpleFilter.class.getName()); + c.tableNamespaceOperations().attachIterator(namespace, setting); + + BatchWriter bw = c.createBatchWriter(tableName3, new BatchWriterConfig()); + Mutation m = new Mutation("r"); + m.put("a", "b", new Value("abcde".getBytes())); + bw.addMutation(m); + bw.flush(); + bw.close(); + + Scanner s = c.createScanner(tableName3, Authorizations.EMPTY); + assertTrue(!s.iterator().hasNext()); } /** @@ -323,6 +355,53 @@ public class TableNamespacesTest { assertTrue(!checkTableHasProp(c, n3 + t, propKey2, propVal3)); } + /** + * This tests adding iterators to a namespace, listing them, and removing them as well as adding and removing constraints + */ + @Test + public void testNamespaceIterators() throws Exception { + Connector c = accumulo.getConnector("root", secret); + + String namespace = "iterator"; + String tableName = namespace + ".table"; + String iter = "thing"; + + c.tableNamespaceOperations().create(namespace); + c.tableOperations().create(tableName); + + IteratorSetting setting = new IteratorSetting(250, iter, SimpleFilter.class.getName()); + HashSet<IteratorScope> scope = new HashSet<IteratorScope>(); + scope.add(IteratorScope.scan); + c.tableNamespaceOperations().attachIterator(namespace, setting, EnumSet.copyOf(scope)); + + BatchWriter bw = c.createBatchWriter(tableName, new BatchWriterConfig()); + Mutation m = new Mutation("r"); + m.put("a", "b", new Value("abcde".getBytes(Constants.UTF8))); + bw.addMutation(m); + bw.flush(); + + Scanner s = c.createScanner(tableName, Authorizations.EMPTY); + assertTrue(!s.iterator().hasNext()); + + assertTrue(c.tableNamespaceOperations().listIterators(namespace).containsKey(iter)); + c.tableNamespaceOperations().removeIterator(namespace, iter, EnumSet.copyOf(scope)); + + c.tableNamespaceOperations().addConstraint(namespace, NumericValueConstraint.class.getName()); + m = new Mutation("rowy"); + m.put("a", "b", new Value("abcde".getBytes(Constants.UTF8))); + try { + bw.addMutation(m); + bw.flush(); + fail(); + } catch (MutationsRejectedException e) { + // supposed to be thrown + } + bw.close(); + + int num = c.tableNamespaceOperations().listConstraints(namespace).get(NumericValueConstraint.class.getName()); + c.tableNamespaceOperations().removeConstraint(namespace, num); + } + private boolean checkTableHasProp(Connector c, String t, String propKey, String propVal) throws AccumuloException, TableNotFoundException { for (Entry<String,String> e : c.tableOperations().getProperties(t)) { if (e.getKey().equals(propKey) && e.getValue().equals(propVal)) { @@ -340,4 +419,12 @@ public class TableNamespacesTest { } return false; } + + public static class SimpleFilter extends Filter { + public boolean accept(Key k, Value v) { + if (k.getColumnFamily().toString().equals("a")) + return false; + return true; + } + } }
