accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [45/61] [abbrv] [partial] accumulo git commit: ACCUMULO-722 put trunk in my sandbox
Date Thu, 03 Mar 2016 22:00:10 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/AccumuloSecurityException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/AccumuloSecurityException.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/AccumuloSecurityException.java
new file mode 100644
index 0000000..d1bb0cb
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/AccumuloSecurityException.java
@@ -0,0 +1,104 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.security.thrift.SecurityErrorCode;
+import org.apache.accumulo.core.security.thrift.ThriftSecurityException;
+
+/**
+ * An Accumulo Exception for security violations, authentication failures, authorization failures, etc.
+ * 
+ */
+public class AccumuloSecurityException extends Exception {
+  private static final long serialVersionUID = 1L;
+  
+  private static String getDefaultErrorMessage(SecurityErrorCode errorcode) {
+    switch (errorcode) {
+      case BAD_CREDENTIALS:
+        return "Username or Password is Invalid";
+      case CONNECTION_ERROR:
+        return "Connection Error Occurred";
+      case PERMISSION_DENIED:
+        return "User does not have permission to perform this action";
+      case USER_DOESNT_EXIST:
+        return "The user does not exist";
+      case USER_EXISTS:
+        return "The user exists";
+      case GRANT_INVALID:
+        return "The GRANT permission cannot be granted or revoked";
+      case BAD_AUTHORIZATIONS:
+        return "The user does not have the specified authorizations assigned";
+      case DEFAULT_SECURITY_ERROR:
+      default:
+        return "Unknown security exception";
+    }
+  }
+  
+  private String user;
+  private SecurityErrorCode errorCode;
+  
+  /**
+   * @return this exception as a thrift exception
+   */
+  public ThriftSecurityException asThriftException() {
+    return new ThriftSecurityException(user, errorCode);
+  }
+  
+  /**
+   * @param user
+   *          the relevant user for the security violation
+   * @param errorcode
+   *          the specific reason for this exception
+   * @param cause
+   *          the exception that caused this violation
+   */
+  public AccumuloSecurityException(String user, SecurityErrorCode errorcode, Throwable cause) {
+    super(getDefaultErrorMessage(errorcode), cause);
+    this.user = user;
+    this.errorCode = errorcode == null ? SecurityErrorCode.DEFAULT_SECURITY_ERROR : errorcode;
+  }
+  
+  /**
+   * @param user
+   *          the relevant user for the security violation
+   * @param errorcode
+   *          the specific reason for this exception
+   */
+  public AccumuloSecurityException(String user, SecurityErrorCode errorcode) {
+    super(getDefaultErrorMessage(errorcode));
+    this.user = user;
+    this.errorCode = errorcode == null ? SecurityErrorCode.DEFAULT_SECURITY_ERROR : errorcode;
+  }
+  
+  /**
+   * @return the relevant user for the security violation
+   */
+  public String getUser() {
+    return user;
+  }
+  
+  /**
+   * @return the specific reason for this exception
+   */
+  public SecurityErrorCode getErrorCode() {
+    return errorCode;
+  }
+  
+  public String getMessage() {
+    return "Error " + errorCode + " - " + super.getMessage();
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchDeleter.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchDeleter.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchDeleter.java
new file mode 100644
index 0000000..15405a0
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchDeleter.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import java.util.Collection;
+
+import org.apache.accumulo.core.data.Range;
+
+/**
+ * Implementations of BatchDeleter support efficient deletion of ranges in accumulo.
+ * 
+ */
+
+public interface BatchDeleter extends ScannerBase {
+  /**
+   * Deletes the ranges specified by {@link #setRanges}.
+   * 
+   * @throws MutationsRejectedException
+   *           this can be thrown when deletion mutations fail
+   * @throws TableNotFoundException
+   *           when the table does not exist
+   */
+  public void delete() throws MutationsRejectedException, TableNotFoundException;
+  
+  /**
+   * Allows deleting multiple ranges efficiently.
+   * 
+   * @param ranges
+   *          specifies the non-overlapping ranges to query
+   */
+  void setRanges(Collection<Range> ranges);
+  
+  /**
+   * Releases any resources.
+   */
+  void close();
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchScanner.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchScanner.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchScanner.java
new file mode 100644
index 0000000..926bda5
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchScanner.java
@@ -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.
+ */
+package org.apache.accumulo.core.client;
+
+import java.util.Collection;
+
+import org.apache.accumulo.core.data.Range;
+
+/**
+ * Implementations of BatchScanner support efficient lookups of many ranges in accumulo.
+ * 
+ * Use this when looking up lots of ranges and you expect each range to contain a small amount of data. Also only use this when you do not care about the
+ * returned data being in sorted order.
+ * 
+ * If you want to lookup a few ranges and expect those ranges to contain a lot of data, then use the Scanner instead. Also, the Scanner will return data in
+ * sorted order, this will not.
+ */
+
+public interface BatchScanner extends ScannerBase {
+  
+  /**
+   * Allows scanning over multiple ranges efficiently.
+   * 
+   * @param ranges
+   *          specifies the non-overlapping ranges to query
+   */
+  void setRanges(Collection<Range> ranges);
+  
+  /**
+   * Cleans up and finalizes the scanner
+   */
+  void close();
+  
+  /**
+   * Sets a timeout threshold for a server to respond. The batch scanner will accomplish as much work as possible before throwing an exception. BatchScanner
+   * iterators will throw a {@link TimedOutException} when all needed servers timeout.
+   * 
+   * <p>
+   * If not set, the timeout defaults to MAX_INT
+   * 
+   * @param timeout
+   *          in seconds
+   */
+  @Override
+  void setTimeOut(int timeout);
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java
new file mode 100644
index 0000000..3f5c6ca
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.data.Mutation;
+
+/**
+ * Send Mutations to a single Table in Accumulo.
+ */
+public interface BatchWriter {
+  
+  /**
+   * Queues one mutation to write.
+   * 
+   * @param m
+   *          the mutation to add
+   * @throws MutationsRejectedException
+   *           this could be thrown because current or previous mutations failed
+   */
+  
+  public void addMutation(Mutation m) throws MutationsRejectedException;
+  
+  /**
+   * Queues several mutations to write.
+   * 
+   * @param iterable
+   *          allows adding any number of mutations iteratively
+   * @throws MutationsRejectedException
+   *           this could be thrown because current or previous mutations failed
+   */
+  public void addMutations(Iterable<Mutation> iterable) throws MutationsRejectedException;
+  
+  /**
+   * Send any buffered mutations to Accumulo immediately.
+   * 
+   * @throws MutationsRejectedException
+   *           this could be thrown because current or previous mutations failed
+   */
+  public void flush() throws MutationsRejectedException;
+  
+  /**
+   * Flush and release any resources.
+   * 
+   * @throws MutationsRejectedException
+   *           this could be thrown because current or previous mutations failed
+   */
+  public void close() throws MutationsRejectedException;
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/ClientSideIteratorScanner.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/ClientSideIteratorScanner.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/ClientSideIteratorScanner.java
new file mode 100644
index 0000000..38ac643
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/ClientSideIteratorScanner.java
@@ -0,0 +1,248 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.apache.accumulo.core.client.impl.ScannerOptions;
+import org.apache.accumulo.core.client.mock.IteratorAdapter;
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
+import org.apache.accumulo.core.data.ArrayByteSequence;
+import org.apache.accumulo.core.data.ByteSequence;
+import org.apache.accumulo.core.data.Column;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.data.thrift.IterInfo;
+import org.apache.accumulo.core.iterators.IteratorEnvironment;
+import org.apache.accumulo.core.iterators.IteratorUtil;
+import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
+import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
+import org.apache.hadoop.io.Text;
+
+/**
+ * A scanner that instantiates iterators on the client side instead of on the tablet server. This can be useful for testing iterators or in cases where you
+ * don't want iterators affecting the performance of tablet servers.<br>
+ * <br>
+ * Suggested usage:<br>
+ * <code>Scanner scanner = new ClientSideIteratorScanner(connector.createScanner(tableName, authorizations));</code><br>
+ * <br>
+ * Iterators added to this scanner will be run in the client JVM. Separate scan iterators can be run on the server side and client side by adding iterators to
+ * the source scanner (which will execute server side) and to the client side scanner (which will execute client side).
+ */
+public class ClientSideIteratorScanner extends ScannerOptions implements Scanner {
+  private int size;
+  private int timeOut;
+  
+  private Range range;
+  private boolean isolated = false;
+  
+  /**
+   * A class that wraps a Scanner in a SortedKeyValueIterator so that other accumulo iterators can use it as a source.
+   */
+  public class ScannerTranslator implements SortedKeyValueIterator<Key,Value> {
+    protected Scanner scanner;
+    Iterator<Entry<Key,Value>> iter;
+    Entry<Key,Value> top = null;
+    
+    /**
+     * Constructs an accumulo iterator from a scanner.
+     * 
+     * @param scanner
+     *          the scanner to iterate over
+     */
+    public ScannerTranslator(Scanner scanner) {
+      this.scanner = scanner;
+    }
+    
+    @Override
+    public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
+      throw new UnsupportedOperationException();
+    }
+    
+    @Override
+    public boolean hasTop() {
+      return top != null;
+    }
+    
+    @Override
+    public void next() throws IOException {
+      if (iter.hasNext())
+        top = iter.next();
+      else
+        top = null;
+    }
+    
+    @Override
+    public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
+      if (!inclusive && columnFamilies.size() > 0)
+        throw new IllegalArgumentException();
+      scanner.setRange(range);
+      scanner.clearColumns();
+      for (ByteSequence colf : columnFamilies) {
+        scanner.fetchColumnFamily(new Text(colf.toArray()));
+      }
+      iter = scanner.iterator();
+      next();
+    }
+    
+    @Override
+    public Key getTopKey() {
+      return top.getKey();
+    }
+    
+    @Override
+    public Value getTopValue() {
+      return top.getValue();
+    }
+    
+    @Override
+    public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
+      return new ScannerTranslator(scanner);
+    }
+  }
+  
+  private ScannerTranslator smi;
+  
+  /**
+   * Constructs a scanner that can execute client-side iterators.
+   * 
+   * @param scanner
+   *          the source scanner
+   */
+  public ClientSideIteratorScanner(Scanner scanner) {
+    smi = new ScannerTranslator(scanner);
+    this.range = scanner.getRange();
+    this.size = scanner.getBatchSize();
+    this.timeOut = scanner.getTimeOut();
+  }
+  
+  /**
+   * Sets the source Scanner.
+   * 
+   * @param scanner
+   */
+  public void setSource(Scanner scanner) {
+    smi = new ScannerTranslator(scanner);
+  }
+  
+  @Override
+  public Iterator<Entry<Key,Value>> iterator() {
+    smi.scanner.setBatchSize(size);
+    smi.scanner.setTimeOut(timeOut);
+    if (isolated)
+      smi.scanner.enableIsolation();
+    else
+      smi.scanner.disableIsolation();
+    
+    TreeMap<Integer,IterInfo> tm = new TreeMap<Integer,IterInfo>();
+    
+    for (IterInfo iterInfo : serverSideIteratorList) {
+      tm.put(iterInfo.getPriority(), iterInfo);
+    }
+    
+    SortedKeyValueIterator<Key,Value> skvi;
+    try {
+      skvi = IteratorUtil.loadIterators(smi, tm.values(), serverSideIteratorOptions, new IteratorEnvironment() {
+        @Override
+        public SortedKeyValueIterator<Key,Value> reserveMapFileReader(String mapFileName) throws IOException {
+          return null;
+        }
+        
+        @Override
+        public AccumuloConfiguration getConfig() {
+          return null;
+        }
+        
+        @Override
+        public IteratorScope getIteratorScope() {
+          return null;
+        }
+        
+        @Override
+        public boolean isFullMajorCompaction() {
+          return false;
+        }
+        
+        @Override
+        public void registerSideChannel(SortedKeyValueIterator<Key,Value> iter) {}
+      }, false);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    
+    Set<ByteSequence> colfs = new TreeSet<ByteSequence>();
+    for (Column c : this.getFetchedColumns()) {
+      colfs.add(new ArrayByteSequence(c.getColumnFamily()));
+    }
+    
+    try {
+      skvi.seek(range, colfs, true);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    
+    return new IteratorAdapter(skvi);
+  }
+  
+  @Override
+  public void setTimeOut(int timeOut) {
+    this.timeOut = timeOut;
+  }
+  
+  @Override
+  public int getTimeOut() {
+    return timeOut;
+  }
+  
+  @Override
+  public void setRange(Range range) {
+    this.range = range;
+  }
+  
+  @Override
+  public Range getRange() {
+    return range;
+  }
+  
+  @Override
+  public void setBatchSize(int size) {
+    this.size = size;
+  }
+  
+  @Override
+  public int getBatchSize() {
+    return size;
+  }
+  
+  @Override
+  public void enableIsolation() {
+    this.isolated = true;
+  }
+  
+  @Override
+  public void disableIsolation() {
+    this.isolated = false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/Connector.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/Connector.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/Connector.java
new file mode 100644
index 0000000..72b3252
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/Connector.java
@@ -0,0 +1,207 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.client.admin.InstanceOperations;
+import org.apache.accumulo.core.client.admin.SecurityOperations;
+import org.apache.accumulo.core.client.admin.TableOperations;
+import org.apache.accumulo.core.security.Authorizations;
+
+/**
+ * Connector connects to an Accumulo instance and allows the user to request readers and writers for the instance as well as various objects that permit
+ * administrative operations.
+ * 
+ * The Connector enforces security on the client side by forcing all API calls to be accompanied by user credentials.
+ */
+public class Connector {
+  final Connector impl;
+  
+  /**
+   * Construct a Connector from an {@link Instance}
+   * 
+   * @deprecated Not for client use
+   * @param instance
+   *          contains the precise connection information to identify the running accumulo instance
+   * @param user
+   *          a valid accumulo user
+   * @param password
+   *          the password for the user
+   * @throws AccumuloException
+   *           when a generic exception occurs
+   * @throws AccumuloSecurityException
+   *           when a user's credentials are invalid
+   * @see Instance#getConnector(String user, byte[] password)
+   */
+  public Connector(Instance instance, String user, byte[] password) throws AccumuloException, AccumuloSecurityException {
+    impl = instance.getConnector(user, password);
+  }
+  
+  /**
+   * @see Instance#getConnector(String user, byte[] password)
+   * @deprecated Not for client use
+   */
+  public Connector() {
+    impl = null;
+  }
+  
+  /**
+   * Factory method to create a BatchScanner connected to Accumulo.
+   * 
+   * @param tableName
+   *          the name of the table to query
+   * @param authorizations
+   *          A set of authorization labels that will be checked against the column visibility of each key in order to filter data. The authorizations passed in
+   *          must be a subset of the accumulo user's set of authorizations. If the accumulo user has authorizations (A1, A2) and authorizations (A2, A3) are
+   *          passed, then an exception will be thrown.
+   * @param numQueryThreads
+   *          the number of concurrent threads to spawn for querying
+   * 
+   * @return BatchScanner object for configuring and querying
+   * @throws TableNotFoundException
+   *           when the specified table doesn't exist
+   */
+  public BatchScanner createBatchScanner(String tableName, Authorizations authorizations, int numQueryThreads) throws TableNotFoundException {
+    return impl.createBatchScanner(tableName, authorizations, numQueryThreads);
+  }
+  
+  /**
+   * Factory method to create a BatchDeleter connected to Accumulo.
+   * 
+   * @param tableName
+   *          the name of the table to query and delete from
+   * @param authorizations
+   *          A set of authorization labels that will be checked against the column visibility of each key in order to filter data. The authorizations passed in
+   *          must be a subset of the accumulo user's set of authorizations. If the accumulo user has authorizations (A1, A2) and authorizations (A2, A3) are
+   *          passed, then an exception will be thrown.
+   * @param numQueryThreads
+   *          the number of concurrent threads to spawn for querying
+   * @param maxMemory
+   *          size in bytes of the maximum memory to batch before writing
+   * @param maxLatency
+   *          size in milliseconds; set to 0 or Long.MAX_VALUE to allow the maximum time to hold a batch before writing
+   * @param maxWriteThreads
+   *          the maximum number of threads to use for writing data to the tablet servers
+   * 
+   * @return BatchDeleter object for configuring and deleting
+   * @throws TableNotFoundException
+   *           when the specified table doesn't exist
+   */
+  public BatchDeleter createBatchDeleter(String tableName, Authorizations authorizations, int numQueryThreads, long maxMemory, long maxLatency,
+      int maxWriteThreads) throws TableNotFoundException {
+    return impl.createBatchDeleter(tableName, authorizations, numQueryThreads, maxMemory, maxLatency, maxWriteThreads);
+  }
+  
+  /**
+   * Factory method to create a BatchWriter connected to Accumulo.
+   * 
+   * @param tableName
+   *          the name of the table to insert data into
+   * @param maxMemory
+   *          size in bytes of the maximum memory to batch before writing
+   * @param maxLatency
+   *          time in milliseconds; set to 0 or Long.MAX_VALUE to allow the maximum time to hold a batch before writing
+   * @param maxWriteThreads
+   *          the maximum number of threads to use for writing data to the tablet servers
+   * 
+   * @return BatchWriter object for configuring and writing data to
+   * @throws TableNotFoundException
+   *           when the specified table doesn't exist
+   */
+  public BatchWriter createBatchWriter(String tableName, long maxMemory, long maxLatency, int maxWriteThreads) throws TableNotFoundException {
+    return impl.createBatchWriter(tableName, maxMemory, maxLatency, maxWriteThreads);
+  }
+  
+  /**
+   * Factory method to create a Multi-Table BatchWriter connected to Accumulo. Multi-table batch writers can queue data for multiple tables, which is good for
+   * ingesting data into multiple tables from the same source
+   * 
+   * @param maxMemory
+   *          size in bytes of the maximum memory to batch before writing
+   * @param maxLatency
+   *          size in milliseconds; set to 0 or Long.MAX_VALUE to allow the maximum time to hold a batch before writing
+   * @param maxWriteThreads
+   *          the maximum number of threads to use for writing data to the tablet servers
+   * 
+   * @return MultiTableBatchWriter object for configuring and writing data to
+   */
+  public MultiTableBatchWriter createMultiTableBatchWriter(long maxMemory, long maxLatency, int maxWriteThreads) {
+    return impl.createMultiTableBatchWriter(maxMemory, maxLatency, maxWriteThreads);
+  }
+  
+  /**
+   * Factory method to create a Scanner connected to Accumulo.
+   * 
+   * @param tableName
+   *          the name of the table to query data from
+   * @param authorizations
+   *          A set of authorization labels that will be checked against the column visibility of each key in order to filter data. The authorizations passed in
+   *          must be a subset of the accumulo user's set of authorizations. If the accumulo user has authorizations (A1, A2) and authorizations (A2, A3) are
+   *          passed, then an exception will be thrown.
+   * 
+   * @return Scanner object for configuring and querying data with
+   * @throws TableNotFoundException
+   *           when the specified table doesn't exist
+   */
+  public Scanner createScanner(String tableName, Authorizations authorizations) throws TableNotFoundException {
+    return impl.createScanner(tableName, authorizations);
+  }
+  
+  /**
+   * Accessor method for internal instance object.
+   * 
+   * @return the internal instance object
+   */
+  public Instance getInstance() {
+    return impl.getInstance();
+  }
+  
+  /**
+   * Get the current user for this connector
+   * 
+   * @return the user name
+   */
+  public String whoami() {
+    return impl.whoami();
+  }
+  
+  /**
+   * Retrieves a TableOperations object to perform table functions, such as create and delete.
+   * 
+   * @return an object to manipulate tables
+   */
+  public synchronized TableOperations tableOperations() {
+    return impl.tableOperations();
+  }
+  
+  /**
+   * Retrieves a SecurityOperations object to perform user security operations, such as creating users.
+   * 
+   * @return an object to modify users and permissions
+   */
+  public synchronized SecurityOperations securityOperations() {
+    return impl.securityOperations();
+  }
+  
+  /**
+   * Retrieves an InstanceOperations object to modify instance configuration.
+   * 
+   * @return an object to modify instance configuration
+   */
+  public synchronized InstanceOperations instanceOperations() {
+    return impl.instanceOperations();
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/Instance.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/Instance.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/Instance.java
new file mode 100644
index 0000000..b3d09ba
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/Instance.java
@@ -0,0 +1,144 @@
+/*
+ * 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;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
+import org.apache.accumulo.core.security.thrift.AuthInfo;
+
+/**
+ * This class represents the information a client needs to know to connect to an instance of accumulo.
+ * 
+ */
+public interface Instance {
+  /**
+   * Returns the location of the tablet server that is serving the root tablet.
+   * 
+   * @return location in "hostname:port" form
+   */
+  public abstract String getRootTabletLocation();
+  
+  /**
+   * Returns the location(s) of the accumulo master and any redundant servers.
+   * 
+   * @return a list of locations in "hostname:port" form
+   */
+  public abstract List<String> getMasterLocations();
+  
+  /**
+   * Returns a unique string that identifies this instance of accumulo.
+   * 
+   * @return a UUID
+   */
+  public abstract String getInstanceID();
+  
+  /**
+   * Returns the instance name given at system initialization time.
+   * 
+   * @return current instance name
+   */
+  public abstract String getInstanceName();
+  
+  /**
+   * Returns a comma-separated list of zookeeper servers the instance is using.
+   * 
+   * @return the zookeeper servers this instance is using in "hostname:port" form
+   */
+  public abstract String getZooKeepers();
+  
+  /**
+   * Returns the zookeeper connection timeout.
+   * 
+   * @return the configured timeout to connect to zookeeper
+   */
+  public abstract int getZooKeepersSessionTimeOut();
+  
+  /**
+   * Returns a connection to accumulo.
+   * 
+   * @param user
+   *          a valid accumulo user
+   * @param pass
+   *          A UTF-8 encoded password. The password may be cleared after making this call.
+   * @return the accumulo Connector
+   * @throws AccumuloException
+   *           when a generic exception occurs
+   * @throws AccumuloSecurityException
+   *           when a user's credentials are invalid
+   */
+  public abstract Connector getConnector(String user, byte[] pass) throws AccumuloException, AccumuloSecurityException;
+  
+  /**
+   * Returns a connection to accumulo.
+   * 
+   * @param auth
+   *          An AuthInfo object.
+   * @return the accumulo Connector
+   * @throws AccumuloException
+   *           when a generic exception occurs
+   * @throws AccumuloSecurityException
+   *           when a user's credentials are invalid
+   */
+  public abstract Connector getConnector(AuthInfo auth) throws AccumuloException, AccumuloSecurityException;
+  
+  /**
+   * Returns a connection to accumulo.
+   * 
+   * @param user
+   *          a valid accumulo user
+   * @param pass
+   *          A UTF-8 encoded password. The password may be cleared after making this call.
+   * @return the accumulo Connector
+   * @throws AccumuloException
+   *           when a generic exception occurs
+   * @throws AccumuloSecurityException
+   *           when a user's credentials are invalid
+   */
+  public abstract Connector getConnector(String user, ByteBuffer pass) throws AccumuloException, AccumuloSecurityException;
+  
+  /**
+   * Returns a connection to this instance of accumulo.
+   * 
+   * @param user
+   *          a valid accumulo user
+   * @param pass
+   *          If a mutable CharSequence is passed in, it may be cleared after this call.
+   * @return the accumulo Connector
+   * @throws AccumuloException
+   *           when a generic exception occurs
+   * @throws AccumuloSecurityException
+   *           when a user's credentials are invalid
+   */
+  public abstract Connector getConnector(String user, CharSequence pass) throws AccumuloException, AccumuloSecurityException;
+  
+  /**
+   * Returns the AccumuloConfiguration to use when interacting with this instance.
+   * 
+   * @return the AccumuloConfiguration that specifies properties related to interacting with this instance
+   */
+  public abstract AccumuloConfiguration getConfiguration();
+  
+  /**
+   * Set the AccumuloConfiguration to use when interacting with this instance.
+   * 
+   * @param conf
+   *          accumulo configuration
+   */
+  public abstract void setConfiguration(AccumuloConfiguration conf);
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/IsolatedScanner.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/IsolatedScanner.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/IsolatedScanner.java
new file mode 100644
index 0000000..16f2c05
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/IsolatedScanner.java
@@ -0,0 +1,272 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.client.impl.IsolationException;
+import org.apache.accumulo.core.client.impl.ScannerOptions;
+import org.apache.accumulo.core.data.ByteSequence;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.PartialKey;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.util.UtilWaitThread;
+import org.apache.hadoop.io.Text;
+
+/**
+ * A scanner that presents a row isolated view of an accumulo table. Rows are buffered in memory on the client side. If you think your rows may not fit into
+ * memory, then you can provide an alternative row buffer factory to the constructor. This would allow rows to be buffered to disk for example.
+ * 
+ */
+
+public class IsolatedScanner extends ScannerOptions implements Scanner {
+  
+  private static class RowBufferingIterator implements Iterator<Entry<Key,Value>> {
+    
+    private Iterator<Entry<Key,Value>> source;
+    private RowBuffer buffer;
+    private Entry<Key,Value> nextRowStart;
+    private Iterator<Entry<Key,Value>> rowIter;
+    private ByteSequence lastRow = null;
+    
+    private Scanner scanner;
+    private ScannerOptions opts;
+    private Range range;
+    private int timeOut;
+    private int batchSize;
+    
+    private void readRow() {
+      
+      ByteSequence row = null;
+      
+      while (true) {
+        buffer.clear();
+        
+        try {
+          if (nextRowStart != null) {
+            buffer.add(nextRowStart);
+            row = nextRowStart.getKey().getRowData();
+            nextRowStart = null;
+          } else if (source.hasNext()) {
+            Entry<Key,Value> entry = source.next();
+            buffer.add(entry);
+            row = entry.getKey().getRowData();
+          }
+          
+          while (source.hasNext()) {
+            Entry<Key,Value> entry = source.next();
+            
+            if (entry.getKey().getRowData().equals(row)) {
+              buffer.add(entry);
+            } else {
+              nextRowStart = entry;
+              break;
+            }
+          }
+          
+          lastRow = row;
+          rowIter = buffer.iterator();
+          // System.out.println("lastRow <- "+lastRow + " "+buffer);
+          return;
+        } catch (IsolationException ie) {
+          Range seekRange = null;
+          
+          nextRowStart = null;
+          
+          if (lastRow == null)
+            seekRange = range;
+          else {
+            Text lastRowText = new Text();
+            lastRowText.set(lastRow.getBackingArray(), lastRow.offset(), lastRow.length());
+            Key startKey = new Key(lastRowText).followingKey(PartialKey.ROW);
+            if (!range.afterEndKey(startKey)) {
+              seekRange = new Range(startKey, true, range.getEndKey(), range.isEndKeyInclusive());
+            }
+            // System.out.println(seekRange);
+          }
+          
+          if (seekRange == null) {
+            buffer.clear();
+            rowIter = buffer.iterator();
+            return;
+          }
+          
+          // wait a moment before retrying
+          UtilWaitThread.sleep(100);
+          
+          source = newIterator(seekRange);
+        }
+      }
+    }
+    
+    private Iterator<Entry<Key,Value>> newIterator(Range r) {
+      synchronized (scanner) {
+        scanner.enableIsolation();
+        scanner.setBatchSize(batchSize);
+        scanner.setTimeOut(timeOut);
+        scanner.setRange(r);
+        setOptions((ScannerOptions) scanner, opts);
+        
+        return scanner.iterator();
+        // return new FaultyIterator(scanner.iterator());
+      }
+    }
+    
+    public RowBufferingIterator(Scanner scanner, ScannerOptions opts, Range range, int timeOut, int batchSize, RowBufferFactory bufferFactory) {
+      this.scanner = scanner;
+      this.opts = new ScannerOptions(opts);
+      this.range = range;
+      this.timeOut = timeOut;
+      this.batchSize = batchSize;
+      
+      buffer = bufferFactory.newBuffer();
+      
+      this.source = newIterator(range);
+      
+      readRow();
+    }
+    
+    @Override
+    public boolean hasNext() {
+      return rowIter.hasNext();
+    }
+    
+    @Override
+    public Entry<Key,Value> next() {
+      Entry<Key,Value> next = rowIter.next();
+      if (!rowIter.hasNext()) {
+        readRow();
+      }
+      
+      return next;
+    }
+    
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+    
+  }
+  
+  public static interface RowBufferFactory {
+    RowBuffer newBuffer();
+  }
+  
+  public static interface RowBuffer extends Iterable<Entry<Key,Value>> {
+    void add(Entry<Key,Value> entry);
+    
+    Iterator<Entry<Key,Value>> iterator();
+    
+    void clear();
+  }
+  
+  public static class MemoryRowBufferFactory implements RowBufferFactory {
+    
+    @Override
+    public RowBuffer newBuffer() {
+      return new MemoryRowBuffer();
+    }
+  }
+  
+  public static class MemoryRowBuffer implements RowBuffer {
+    
+    private ArrayList<Entry<Key,Value>> buffer = new ArrayList<Entry<Key,Value>>();
+    
+    @Override
+    public void add(Entry<Key,Value> entry) {
+      buffer.add(entry);
+    }
+    
+    @Override
+    public Iterator<Entry<Key,Value>> iterator() {
+      return buffer.iterator();
+    }
+    
+    @Override
+    public void clear() {
+      buffer.clear();
+    }
+    
+  }
+  
+  private Scanner scanner;
+  private Range range;
+  private int timeOut;
+  private int batchSize;
+  private RowBufferFactory bufferFactory;
+  
+  public IsolatedScanner(Scanner scanner) {
+    this(scanner, new MemoryRowBufferFactory());
+  }
+  
+  public IsolatedScanner(Scanner scanner, RowBufferFactory bufferFactory) {
+    this.scanner = scanner;
+    this.range = scanner.getRange();
+    this.timeOut = scanner.getTimeOut();
+    this.batchSize = scanner.getBatchSize();
+    this.bufferFactory = bufferFactory;
+  }
+  
+  @Override
+  public Iterator<Entry<Key,Value>> iterator() {
+    return new RowBufferingIterator(scanner, this, range, timeOut, batchSize, bufferFactory);
+  }
+  
+  @Override
+  public void setTimeOut(int timeOut) {
+    this.timeOut = timeOut;
+  }
+  
+  @Override
+  public int getTimeOut() {
+    return timeOut;
+  }
+  
+  @Override
+  public void setRange(Range range) {
+    this.range = range;
+    ;
+  }
+  
+  @Override
+  public Range getRange() {
+    return range;
+  }
+  
+  @Override
+  public void setBatchSize(int size) {
+    this.batchSize = size;
+  }
+  
+  @Override
+  public int getBatchSize() {
+    return batchSize;
+  }
+  
+  @Override
+  public void enableIsolation() {
+    // aye aye captain, already done sir
+  }
+  
+  @Override
+  public void disableIsolation() {
+    throw new UnsupportedOperationException();
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/IteratorSetting.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/IteratorSetting.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/IteratorSetting.java
new file mode 100644
index 0000000..a3ea003
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/IteratorSetting.java
@@ -0,0 +1,300 @@
+/*
+ * 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;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
+import org.apache.accumulo.core.util.ArgumentChecker;
+import org.apache.accumulo.core.util.Pair;
+import org.apache.hadoop.io.Text;
+
+/**
+ * Configure an iterator for minc, majc, and/or scan. By default, IteratorSetting will be configured for scan.
+ * 
+ * Every iterator has a priority, a name, a class, a set of scopes, and configuration parameters.
+ * 
+ * A typical use case configured for scan:
+ * 
+ * <pre>
+ * IteratorSetting cfg = new IteratorSetting(priority, &quot;myIter&quot;, MyIterator.class);
+ * MyIterator.addOption(cfg, 42);
+ * scanner.addScanIterator(cfg);
+ * </pre>
+ */
+public class IteratorSetting {
+  private int priority;
+  private String name;
+  private String iteratorClass;
+  private Map<String,String> properties;
+  
+  /**
+   * Get layer at which this iterator applies. See {@link #setPriority(int)} for how the priority is used.
+   * 
+   * @return the priority of this Iterator
+   */
+  public int getPriority() {
+    return priority;
+  }
+  
+  /**
+   * Set layer at which this iterator applies.
+   * 
+   * @param priority
+   *          determines the order in which iterators are applied (system iterators are always applied first, then user-configured iterators, lowest priority
+   *          first)
+   */
+  public void setPriority(int priority) {
+    ArgumentChecker.strictlyPositive(priority);
+    this.priority = priority;
+  }
+  
+  /**
+   * Get the iterator's name.
+   * 
+   * @return the name of the iterator
+   */
+  public String getName() {
+    return name;
+  }
+  
+  /**
+   * Set the iterator's name. Must be a simple alphanumeric identifier.
+   * 
+   * @param name
+   */
+  public void setName(String name) {
+    ArgumentChecker.notNull(name);
+    this.name = name;
+  }
+  
+  /**
+   * Get the name of the class that implements the iterator.
+   * 
+   * @return the iterator's class name
+   */
+  public String getIteratorClass() {
+    return iteratorClass;
+  }
+  
+  /**
+   * Set the name of the class that implements the iterator. The class does not have to be present on the client, but it must be available to all tablet
+   * servers.
+   * 
+   * @param iteratorClass
+   */
+  public void setIteratorClass(String iteratorClass) {
+    ArgumentChecker.notNull(iteratorClass);
+    this.iteratorClass = iteratorClass;
+  }
+  
+  /**
+   * Constructs an iterator setting configured for the scan scope with no parameters. (Parameters can be added later.)
+   * 
+   * @param priority
+   *          the priority for the iterator (see {@link #setPriority(int)})
+   * @param name
+   *          the distinguishing name for the iterator
+   * @param iteratorClass
+   *          the fully qualified class name for the iterator
+   */
+  public IteratorSetting(int priority, String name, String iteratorClass) {
+    this(priority, name, iteratorClass, new HashMap<String,String>());
+  }
+  
+  /**
+   * Constructs an iterator setting configured for the specified scopes with the specified parameters.
+   * 
+   * @param priority
+   *          the priority for the iterator (see {@link #setPriority(int)})
+   * @param name
+   *          the distinguishing name for the iterator
+   * @param iteratorClass
+   *          the fully qualified class name for the iterator
+   * @param properties
+   *          any properties for the iterator
+   */
+  public IteratorSetting(int priority, String name, String iteratorClass, Map<String,String> properties) {
+    setPriority(priority);
+    setName(name);
+    setIteratorClass(iteratorClass);
+    this.properties = new HashMap<String,String>();
+    addOptions(properties);
+  }
+  
+  /**
+   * Constructs an iterator setting using the given class's SimpleName for the iterator name. The iterator setting will be configured for the scan scope with no
+   * parameters.
+   * 
+   * @param priority
+   *          the priority for the iterator (see {@link #setPriority(int)})
+   * @param iteratorClass
+   *          the class for the iterator
+   */
+  public IteratorSetting(int priority, Class<? extends SortedKeyValueIterator<Key,Value>> iteratorClass) {
+    this(priority, iteratorClass.getSimpleName(), iteratorClass.getName());
+  }
+  
+  /**
+   * 
+   * Constructs an iterator setting using the given class's SimpleName for the iterator name and configured for the specified scopes with the specified
+   * parameters.
+   * 
+   * @param priority
+   *          the priority for the iterator (see {@link #setPriority(int)})
+   * @param iteratorClass
+   *          the class for the iterator
+   * @param properties
+   *          any properties for the iterator
+   */
+  public IteratorSetting(int priority, Class<? extends SortedKeyValueIterator<Key,Value>> iteratorClass, Map<String,String> properties) {
+    this(priority, iteratorClass.getSimpleName(), iteratorClass.getName(), properties);
+  }
+  
+  /**
+   * Constructs an iterator setting configured for the scan scope with no parameters.
+   * 
+   * @param priority
+   *          the priority for the iterator (see {@link #setPriority(int)})
+   * @param name
+   *          the distinguishing name for the iterator
+   * @param iteratorClass
+   *          the class for the iterator
+   */
+  public IteratorSetting(int priority, String name, Class<? extends SortedKeyValueIterator<Key,Value>> iteratorClass) {
+    this(priority, name, iteratorClass.getName());
+  }
+  
+  /**
+   * Add another option to the iterator.
+   * 
+   * @param option
+   *          the name of the option
+   * @param value
+   *          the value of the option
+   */
+  public void addOption(String option, String value) {
+    ArgumentChecker.notNull(option, value);
+    properties.put(option, value);
+  }
+  
+  /**
+   * Remove an option from the iterator.
+   * 
+   * @param option
+   *          the name of the option
+   * @return the value previously associated with the option, or null if no such option existed
+   */
+  public String removeOption(String option) {
+    ArgumentChecker.notNull(option);
+    return properties.remove(option);
+  }
+  
+  /**
+   * Add many options to the iterator.
+   * 
+   * @param propertyEntries
+   *          a set of entries to add to the options
+   */
+  public void addOptions(Set<Entry<String,String>> propertyEntries) {
+    ArgumentChecker.notNull(propertyEntries);
+    for (Entry<String,String> keyValue : propertyEntries) {
+      addOption(keyValue.getKey(), keyValue.getValue());
+    }
+  }
+  
+  /**
+   * Add many options to the iterator.
+   * 
+   * @param properties
+   *          a map of entries to add to the options
+   */
+  public void addOptions(Map<String,String> properties) {
+    ArgumentChecker.notNull(properties);
+    addOptions(properties.entrySet());
+  }
+  
+  /**
+   * Get the configuration parameters for this iterator.
+   * 
+   * @return the properties
+   */
+  public Map<String,String> getOptions() {
+    return Collections.unmodifiableMap(properties);
+  }
+  
+  /**
+   * Remove all options from the iterator.
+   */
+  public void clearOptions() {
+    properties.clear();
+  }
+  
+  /**
+   * @see java.lang.Object#toString()
+   */
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("name:");
+    sb.append(name);
+    sb.append(", priority:");
+    sb.append(Integer.toString(priority));
+    sb.append(", class:");
+    sb.append(iteratorClass);
+    sb.append(", properties:");
+    sb.append(properties);
+    return sb.toString();
+  }
+  
+  /**
+   * A convenience class for passing column family and column qualifiers to iterator configuration methods.
+   */
+  public static class Column extends Pair<Text,Text> {
+    
+    public Column(Text columnFamily, Text columnQualifier) {
+      super(columnFamily, columnQualifier);
+    }
+    
+    public Column(Text columnFamily) {
+      super(columnFamily, null);
+    }
+    
+    public Column(String columnFamily, String columnQualifier) {
+      super(new Text(columnFamily), new Text(columnQualifier));
+    }
+    
+    public Column(String columnFamily) {
+      super(new Text(columnFamily), null);
+    }
+    
+    public Text getColumnFamily() {
+      return getFirst();
+    }
+    
+    public Text getColumnQualifier() {
+      return getSecond();
+    }
+    
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/MultiTableBatchWriter.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/MultiTableBatchWriter.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/MultiTableBatchWriter.java
new file mode 100644
index 0000000..eda5fa7
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/MultiTableBatchWriter.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+/**
+ * This class enables efficient batch writing to multiple tables. When creating a batch writer for each table, each has its own memory and network resources.
+ * Using this class these resources may be shared among multiple tables.
+ * 
+ */
+public interface MultiTableBatchWriter {
+  
+  /**
+   * Returns a BatchWriter for a particular table.
+   * 
+   * @param table
+   *          the name of a table whose batch writer you wish to retrieve
+   * @return an instance of a batch writer for the specified table
+   * @throws AccumuloException
+   *           when a general exception occurs with accumulo
+   * @throws AccumuloSecurityException
+   *           when the user is not allowed to insert data into that table
+   * @throws TableNotFoundException
+   *           when the table does not exist
+   */
+  public BatchWriter getBatchWriter(String table) throws AccumuloException, AccumuloSecurityException, TableNotFoundException;
+  
+  /**
+   * Send mutations for all tables to accumulo.
+   * 
+   * @throws MutationsRejectedException
+   *           when queued mutations are unable to be inserted
+   */
+  public void flush() throws MutationsRejectedException;
+  
+  /**
+   * Flush and release all resources.
+   * 
+   * @throws MutationsRejectedException
+   *           when queued mutations are unable to be inserted
+   * 
+   */
+  public void close() throws MutationsRejectedException;
+  
+  /**
+   * Returns true if this batch writer has been closed.
+   * 
+   * @return true if this batch writer has been closed
+   */
+  public boolean isClosed();
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
new file mode 100644
index 0000000..d4f5e66
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.accumulo.core.data.ConstraintViolationSummary;
+import org.apache.accumulo.core.data.KeyExtent;
+
+/**
+ * Communicate the failed mutations of a BatchWriter back to the client.
+ * 
+ */
+public class MutationsRejectedException extends AccumuloException {
+  private static final long serialVersionUID = 1L;
+  
+  private List<ConstraintViolationSummary> cvsl;
+  private ArrayList<KeyExtent> af;
+  private Collection<String> es;
+  private int unknownErrors;
+  
+  /**
+   * @param cvsList
+   *          list of constraint violations
+   * @param af
+   *          authorization failures
+   * @param serverSideErrors
+   *          server side errors
+   * @param unknownErrors
+   *          number of unknown errors
+   */
+  public MutationsRejectedException(List<ConstraintViolationSummary> cvsList, ArrayList<KeyExtent> af, Collection<String> serverSideErrors, int unknownErrors,
+      Throwable cause) {
+    super("# constraint violations : " + cvsList.size() + "  # authorization failures : " + af.size() + "  # server errors " + serverSideErrors.size()
+        + " # exceptions " + unknownErrors, cause);
+    this.cvsl = cvsList;
+    this.af = af;
+    this.es = serverSideErrors;
+    this.unknownErrors = unknownErrors;
+  }
+  
+  /**
+   * @return the internal list of constraint violations
+   */
+  public List<ConstraintViolationSummary> getConstraintViolationSummaries() {
+    return cvsl;
+  }
+  
+  /**
+   * @return the internal list of authorization failures
+   */
+  public List<KeyExtent> getAuthorizationFailures() {
+    return af;
+  }
+  
+  /**
+   * 
+   * @return A list of servers that had internal errors when mutations were written
+   * 
+   */
+  public Collection<String> getErrorServers() {
+    return es;
+  }
+  
+  /**
+   * 
+   * @return a count of unknown exceptions that occurred during processing
+   */
+  public int getUnknownExceptions() {
+    return unknownErrors;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/RowIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/RowIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/RowIterator.java
new file mode 100644
index 0000000..005f697
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/RowIterator.java
@@ -0,0 +1,164 @@
+/*
+ * 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;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.util.PeekingIterator;
+import org.apache.hadoop.io.Text;
+
+/**
+ * Group Key/Value pairs into Iterators over rows. Suggested usage:
+ * 
+ * <pre>
+ * RowIterator rowIterator = new RowIterator(connector.createScanner(tableName, authorizations));
+ * </pre>
+ */
+public class RowIterator implements Iterator<Iterator<Entry<Key,Value>>> {
+  
+  /**
+   * Iterate over entries in a single row.
+   */
+  private static class SingleRowIter implements Iterator<Entry<Key,Value>> {
+    private PeekingIterator<Entry<Key,Value>> source;
+    private Text currentRow = null;
+    private long count = 0;
+    private boolean disabled = false;
+    
+    /**
+     * SingleRowIter must be passed a PeekingIterator so that it can peek at the next entry to see if it belongs in the current row or not.
+     */
+    public SingleRowIter(PeekingIterator<Entry<Key,Value>> source) {
+      this.source = source;
+      if (source.hasNext())
+        currentRow = source.peek().getKey().getRow();
+    }
+    
+    @Override
+    public boolean hasNext() {
+      if (disabled)
+        throw new IllegalStateException("SingleRowIter no longer valid");
+      return currentRow != null;
+    }
+    
+    @Override
+    public Entry<Key,Value> next() {
+      if (disabled)
+        throw new IllegalStateException("SingleRowIter no longer valid");
+      return _next();
+    }
+    
+    private Entry<Key,Value> _next() {
+      if (currentRow == null)
+        throw new NoSuchElementException();
+      count++;
+      Entry<Key,Value> kv = source.next();
+      if (!source.hasNext() || !source.peek().getKey().getRow().equals(currentRow)) {
+        currentRow = null;
+      }
+      return kv;
+    }
+    
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * Get a count of entries read from the row (only equals the number of entries in the row when the row has been read fully).
+     */
+    public long getCount() {
+      return count;
+    }
+    
+    /**
+     * Consume the rest of the row. Disables the iterator from future use.
+     */
+    public void consume() {
+      disabled = true;
+      while (currentRow != null)
+        _next();
+    }
+  }
+  
+  private final PeekingIterator<Entry<Key,Value>> iter;
+  private long count = 0;
+  private SingleRowIter lastIter = null;
+  
+  /**
+   * Create an iterator from an (ordered) sequence of KeyValue pairs.
+   * 
+   * @param iterator
+   */
+  public RowIterator(Iterator<Entry<Key,Value>> iterator) {
+    this.iter = new PeekingIterator<Entry<Key,Value>>(iterator);
+  }
+  
+  /**
+   * Create an iterator from an Iterable.
+   * 
+   * @param iterable
+   */
+  public RowIterator(Iterable<Entry<Key,Value>> iterable) {
+    this(iterable.iterator());
+  }
+  
+  /**
+   * Returns true if there is at least one more row to get.
+   * 
+   * If the last row hasn't been fully read, this method will read through the end of the last row so it can determine if the underlying iterator has a next
+   * row. The last row is disabled from future use.
+   */
+  @Override
+  public boolean hasNext() {
+    if (lastIter != null) {
+      lastIter.consume();
+      count += lastIter.getCount();
+      lastIter = null;
+    }
+    return iter.hasNext();
+  }
+  
+  /**
+   * Fetch the next row.
+   */
+  @Override
+  public Iterator<Entry<Key,Value>> next() {
+    if (!hasNext())
+      throw new NoSuchElementException();
+    return lastIter = new SingleRowIter(iter);
+  }
+  
+  /**
+   * Unsupported.
+   */
+  @Override
+  public void remove() {
+    throw new UnsupportedOperationException();
+  }
+  
+  /**
+   * Get a count of the total number of entries in all rows read so far.
+   */
+  public long getKVCount() {
+    return count;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/Scanner.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/Scanner.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/Scanner.java
new file mode 100644
index 0000000..9388ddc
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/Scanner.java
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.data.Range;
+
+/**
+ * Scans a table over a given range.
+ * 
+ * "Clients can iterate over multiple column families, and there are several mechanisms for limiting the rows, columns, and timestamps traversed by a scan. For
+ * example, we could restrict [a] scan ... to only produce anchors whose columns match [a] regular expression ..., or to only produce anchors whose timestamps
+ * fall within ten days of the current time."
+ */
+public interface Scanner extends ScannerBase {
+  
+  /**
+   * Sets the range of keys to scan over.
+   * 
+   * @param range
+   *          key range to begin and end scan
+   */
+  public void setRange(Range range);
+  
+  /**
+   * Returns the range of keys to scan over.
+   * 
+   * @return the range configured for this scanner
+   */
+  public Range getRange();
+  
+  /**
+   * Sets the number of Key/Value pairs that will be fetched at a time from a tablet server.
+   * 
+   * @param size
+   *          the number of Key/Value pairs to fetch per call to Accumulo
+   */
+  public void setBatchSize(int size);
+  
+  /**
+   * Returns the batch size (number of Key/Value pairs) that will be fetched at a time from a tablet server.
+   * 
+   * @return the batch size configured for this scanner
+   */
+  public int getBatchSize();
+  
+  /**
+   * Enables row isolation. Writes that occur to a row after a scan of that row has begun will not be seen if this option is enabled.
+   */
+  public void enableIsolation();
+  
+  /**
+   * Disables row isolation. Writes that occur to a row after a scan of that row has begun may be seen if this option is enabled.
+   */
+  void disableIsolation();
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/ScannerBase.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/ScannerBase.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/ScannerBase.java
new file mode 100644
index 0000000..162a8cf
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/ScannerBase.java
@@ -0,0 +1,118 @@
+/*
+ * 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;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.Text;
+
+/**
+ * This class hosts configuration methods that are shared between different types of scanners.
+ * 
+ */
+public interface ScannerBase extends Iterable<Entry<Key,Value>> {
+  
+  /**
+   * Add a server-side scan iterator.
+   * 
+   * @param cfg
+   *          fully specified scan-time iterator, including all options for the iterator. Any changes to the iterator setting after this call are not propagated
+   *          to the stored iterator.
+   * @throws IllegalArgumentException
+   *           if the setting conflicts with existing iterators
+   */
+  public void addScanIterator(IteratorSetting cfg);
+  
+  /**
+   * Remove an iterator from the list of iterators.
+   * 
+   * @param iteratorName
+   *          nickname used for the iterator
+   */
+  public void removeScanIterator(String iteratorName);
+  
+  /**
+   * Update the options for an iterator. Note that this does <b>not</b> change the iterator options during a scan, it just replaces the given option on a
+   * configured iterator before a scan is started.
+   * 
+   * @param iteratorName
+   *          the name of the iterator to change
+   * @param key
+   *          the name of the option
+   * @param value
+   *          the new value for the named option
+   */
+  public void updateScanIteratorOption(String iteratorName, String key, String value);
+  
+  /**
+   * Adds a column family to the list of columns that will be fetched by this scanner. By default when no columns have been added the scanner fetches all
+   * columns.
+   * 
+   * @param col
+   *          the column family to be fetched
+   */
+  public void fetchColumnFamily(Text col);
+  
+  /**
+   * Adds a column to the list of columns that will be fetched by this scanner. The column is identified by family and qualifier. By default when no columns
+   * have been added the scanner fetches all columns.
+   * 
+   * @param colFam
+   *          the column family of the column to be fetched
+   * @param colQual
+   *          the column qualifier of the column to be fetched
+   */
+  public void fetchColumn(Text colFam, Text colQual);
+  
+  /**
+   * Clears the columns to be fetched (useful for resetting the scanner for reuse). Once cleared, the scanner will fetch all columns.
+   */
+  public void clearColumns();
+  
+  /**
+   * Clears scan iterators prior to returning a scanner to the pool.
+   */
+  public void clearScanIterators();
+  
+  /**
+   * Returns an iterator over an accumulo table. This iterator uses the options that are currently set for its lifetime, so setting options will have no effect
+   * on existing iterators.
+   * 
+   * Keys returned by the iterator are not guaranteed to be in sorted order.
+   * 
+   * @return an iterator over Key,Value pairs which meet the restrictions set on the scanner
+   */
+  public Iterator<Entry<Key,Value>> iterator();
+  
+  /**
+   * This setting determines how long a scanner will automatically retry when a failure occurs. By default a scanner will retry forever.
+   * 
+   * @param timeOut
+   *          in seconds
+   */
+  public void setTimeOut(int timeOut);
+  
+  /**
+   * Returns the setting for how long a scanner will automatically retry when a failure occurs.
+   * 
+   * @return the timeout configured for this scanner
+   */
+  public int getTimeOut();
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/TableDeletedException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/TableDeletedException.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableDeletedException.java
new file mode 100644
index 0000000..bc0b105
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableDeletedException.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ * This exception is thrown if a table is deleted after an operation starts.
+ * 
+ * For example if table A exist when a scan is started, but is deleted during the scan then this exception is thrown.
+ * 
+ */
+
+public class TableDeletedException extends RuntimeException {
+  
+  private static final long serialVersionUID = 1L;
+  private String tableId;
+  
+  public TableDeletedException(String tableId) {
+    super("Table ID " + tableId + " was deleted");
+    this.tableId = tableId;
+  }
+  
+  public String getTableId() {
+    return tableId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/TableExistsException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/TableExistsException.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableExistsException.java
new file mode 100644
index 0000000..bec008d
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableExistsException.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
+
+/**
+ * Thrown when the table specified already exists, and it was expected that it didn't
+ */
+public class TableExistsException extends Exception {
+  /**
+   * Exception to throw if an operation is attempted on a table that already exists.
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+  
+  /**
+   * @param tableId
+   *          the internal id of the table that exists
+   * @param tableName
+   *          the visible name of the table that exists
+   * @param description
+   *          the specific reason why it failed
+   */
+  public TableExistsException(String tableId, String tableName, String description) {
+    super("Table" + (tableName != null && !tableName.isEmpty() ? " " + tableName : "") + (tableId != null && !tableId.isEmpty() ? " (Id=" + tableId + ")" : "")
+        + " exists" + (description != null && !description.isEmpty() ? " (" + description + ")" : ""));
+  }
+  
+  /**
+   * @param tableId
+   *          the internal id of the table that exists
+   * @param tableName
+   *          the visible name of the table that exists
+   * @param description
+   *          the specific reason why it failed
+   * @param cause
+   *          the exception that caused this failure
+   */
+  public TableExistsException(String tableId, String tableName, String description, Throwable cause) {
+    this(tableId, tableName, description);
+    super.initCause(cause);
+  }
+  
+  /**
+   * @param e
+   *          constructs an exception from a thrift exception
+   */
+  public TableExistsException(ThriftTableOperationException e) {
+    this(e.getTableId(), e.getTableName(), e.getDescription(), e);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/TableNotFoundException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/TableNotFoundException.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableNotFoundException.java
new file mode 100644
index 0000000..88ab449
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableNotFoundException.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
+
+/**
+ * Thrown when the table specified doesn't exist when it was expected to
+ */
+public class TableNotFoundException extends Exception {
+  /**
+   * Exception to throw if an operation is attempted on a table that doesn't exist.
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+  
+  private String tableName;
+  
+  /**
+   * @param tableId
+   *          the internal id of the table that was sought
+   * @param tableName
+   *          the visible name of the table that was sought
+   * @param description
+   *          the specific reason why it failed
+   */
+  public TableNotFoundException(String tableId, String tableName, String description) {
+    super("Table" + (tableName != null && !tableName.isEmpty() ? " " + tableName : "") + (tableId != null && !tableId.isEmpty() ? " (Id=" + tableId + ")" : "")
+        + " does not exist" + (description != null && !description.isEmpty() ? " (" + description + ")" : ""));
+    this.tableName = tableName;
+  }
+  
+  /**
+   * @param tableId
+   *          the internal id of the table that was sought
+   * @param tableName
+   *          the visible name of the table that was sought
+   * @param description
+   *          the specific reason why it failed
+   * @param cause
+   *          the exception that caused this failure
+   */
+  public TableNotFoundException(String tableId, String tableName, String description, Throwable cause) {
+    this(tableId, tableName, description);
+    super.initCause(cause);
+  }
+  
+  /**
+   * @param e
+   *          constructs an exception from a thrift exception
+   */
+  public TableNotFoundException(ThriftTableOperationException e) {
+    this(e.getTableId(), e.getTableName(), e.getDescription(), e);
+  }
+  
+  /**
+   * @return the name of the table sought
+   */
+  public String getTableName() {
+    return tableName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java
new file mode 100644
index 0000000..9edb904
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.client.impl.Tables;
+
+public class TableOfflineException extends RuntimeException {
+  
+  private static final long serialVersionUID = 1L;
+  
+  private static String getTableName(Instance instance, String tableId) {
+    if (tableId == null)
+      return " <unknown table> ";
+    try {
+      String tableName = Tables.getTableName(instance, tableId);
+      return tableName + " (" + tableId + ")";
+    } catch (TableNotFoundException e) {
+      return " <unknown table> (" + tableId + ")";
+    }
+  }
+  
+  public TableOfflineException(Instance instance, String tableId) {
+    super("Table " + getTableName(instance, tableId) + " is offline");
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/client/TimedOutException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/client/TimedOutException.java b/1.5/core/src/main/java/org/apache/accumulo/core/client/TimedOutException.java
new file mode 100644
index 0000000..8dedf2c
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/client/TimedOutException.java
@@ -0,0 +1,49 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * 
+ */
+public class TimedOutException extends RuntimeException {
+  
+  private Set<String> timedoutServers;
+  
+  private static final long serialVersionUID = 1L;
+  
+  private static String shorten(Set<String> set) {
+    if (set.size() < 10) {
+      return set.toString();
+    }
+    
+    return new ArrayList<String>(set).subList(0, 10).toString() + " ... " + (set.size() - 10) + " servers not shown";
+  }
+
+  public TimedOutException(Set<String> timedoutServers) {
+    super("Servers timed out " + shorten(timedoutServers));
+    this.timedoutServers = timedoutServers;
+    
+  }
+
+  public Set<String> getTimedOutSevers() {
+    return Collections.unmodifiableSet(timedoutServers);
+  }
+}


Mime
View raw message