accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [20/61] [abbrv] [partial] accumulo git commit: ACCUMULO-722 put trunk in my sandbox
Date Thu, 03 Mar 2016 21:59:45 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LargeRowFilter.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LargeRowFilter.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LargeRowFilter.java
new file mode 100644
index 0000000..be60b50
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LargeRowFilter.java
@@ -0,0 +1,26 @@
+/*
+ * 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.iterators;
+
+/**
+ * This class remains here for backwards compatibility.
+ * 
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.LargeRowFilter}
+ */
+public class LargeRowFilter extends org.apache.accumulo.core.iterators.user.LargeRowFilter {
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LongCombiner.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LongCombiner.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LongCombiner.java
new file mode 100644
index 0000000..2684748
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/LongCombiner.java
@@ -0,0 +1,239 @@
+/*
+ * 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.iterators;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.WritableUtils;
+
+/**
+ * A TypedValueCombiner that translates each Value to a Long before reducing, then encodes the reduced Long back to a Value.
+ * 
+ * Subclasses must implement a typedReduce method: public Long typedReduce(Key key, Iterator<Long> iter);
+ * 
+ * This typedReduce method will be passed the most recent Key and an iterator over the Values (translated to Longs) for all non-deleted versions of that Key.
+ * 
+ * A required option for this Combiner is "type" which indicates which type of Encoder to use to encode and decode Longs into Values. Supported types are
+ * VARNUM, LONG, and STRING which indicate the VarNumEncoder, LongEncoder, and StringEncoder respectively.
+ */
+public abstract class LongCombiner extends TypedValueCombiner<Long> {
+  public static final Encoder<Long> FIXED_LEN_ENCODER = new FixedLenEncoder();
+  public static final Encoder<Long> VAR_LEN_ENCODER = new VarLenEncoder();
+  public static final Encoder<Long> STRING_ENCODER = new StringEncoder();
+  
+  protected static final String TYPE = "type";
+  protected static final String CLASS_PREFIX = "class:";
+  
+  public static enum Type {
+    /**
+     * indicates a variable-length encoding of a Long using {@link LongCombiner.VarLenEncoder}
+     */
+    VARLEN,
+    /**
+     * indicates a fixed-length (8-byte) encoding of a Long using {@link LongCombiner.FixedLenEncoder}
+     */
+    FIXEDLEN,
+    /**
+     * indicates a string representation of a Long using {@link LongCombiner.StringEncoder}
+     */
+    STRING
+  }
+  
+  @Override
+  public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
+    super.init(source, options, env);
+    setEncoder(options);
+  }
+  
+  private void setEncoder(Map<String,String> options) {
+    String type = options.get(TYPE);
+    if (type == null)
+      throw new IllegalArgumentException("no type specified");
+    if (type.startsWith(CLASS_PREFIX)) {
+      setEncoder(type.substring(CLASS_PREFIX.length()));
+      testEncoder(42l);
+    } else {
+      switch (Type.valueOf(type)) {
+        case VARLEN:
+          setEncoder(VAR_LEN_ENCODER);
+          return;
+        case FIXEDLEN:
+          setEncoder(FIXED_LEN_ENCODER);
+          return;
+        case STRING:
+          setEncoder(STRING_ENCODER);
+          return;
+        default:
+          throw new IllegalArgumentException();
+      }
+    }
+  }
+  
+  @Override
+  public IteratorOptions describeOptions() {
+    IteratorOptions io = super.describeOptions();
+    io.setName("longcombiner");
+    io.setDescription("LongCombiner can interpret Values as Longs in a variety of encodings (variable length, fixed length, or string) before combining");
+    io.addNamedOption(TYPE, "<VARLEN|FIXEDLEN|STRING|fullClassName>");
+    return io;
+  }
+  
+  @Override
+  public boolean validateOptions(Map<String,String> options) {
+    super.validateOptions(options);
+    setEncoder(options);
+    return true;
+  }
+  
+  /**
+   * An Encoder that uses a variable-length encoding for Longs. It uses WritableUtils.writeVLong and WritableUtils.readVLong for encoding and decoding.
+   */
+  public static class VarLenEncoder implements Encoder<Long> {
+    @Override
+    public byte[] encode(Long v) {
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      DataOutputStream dos = new DataOutputStream(baos);
+      
+      try {
+        WritableUtils.writeVLong(dos, v);
+      } catch (IOException e) {
+        throw new NumberFormatException(e.getMessage());
+      }
+      
+      return baos.toByteArray();
+    }
+    
+    @Override
+    public Long decode(byte[] b) {
+      DataInputStream dis = new DataInputStream(new ByteArrayInputStream(b));
+      try {
+        return WritableUtils.readVLong(dis);
+      } catch (IOException e) {
+        throw new ValueFormatException(e);
+      }
+    }
+  }
+  
+  /**
+   * An Encoder that uses an 8-byte encoding for Longs.
+   */
+  public static class FixedLenEncoder implements Encoder<Long> {
+    @Override
+    public byte[] encode(Long l) {
+      byte[] b = new byte[8];
+      b[0] = (byte) (l >>> 56);
+      b[1] = (byte) (l >>> 48);
+      b[2] = (byte) (l >>> 40);
+      b[3] = (byte) (l >>> 32);
+      b[4] = (byte) (l >>> 24);
+      b[5] = (byte) (l >>> 16);
+      b[6] = (byte) (l >>> 8);
+      b[7] = (byte) (l >>> 0);
+      return b;
+    }
+    
+    @Override
+    public Long decode(byte[] b) {
+      return decode(b, 0);
+    }
+    
+    public static long decode(byte[] b, int offset) {
+      if (b.length < offset + 8)
+        throw new ValueFormatException("trying to convert to long, but byte array isn't long enough, wanted " + (offset + 8) + " found " + b.length);
+      return (((long) b[offset + 0] << 56) + ((long) (b[offset + 1] & 255) << 48) + ((long) (b[offset + 2] & 255) << 40) + ((long) (b[offset + 3] & 255) << 32)
+          + ((long) (b[offset + 4] & 255) << 24) + ((b[offset + 5] & 255) << 16) + ((b[offset + 6] & 255) << 8) + ((b[offset + 7] & 255) << 0));
+    }
+  }
+  
+  /**
+   * An Encoder that uses a String representation of Longs. It uses Long.toString and Long.parseLong for encoding and decoding.
+   */
+  public static class StringEncoder implements Encoder<Long> {
+    @Override
+    public byte[] encode(Long v) {
+      return Long.toString(v).getBytes();
+    }
+    
+    @Override
+    public Long decode(byte[] b) {
+      try {
+        return Long.parseLong(new String(b));
+      } catch (NumberFormatException nfe) {
+        throw new ValueFormatException(nfe);
+      }
+    }
+  }
+  
+  public static long safeAdd(long a, long b) {
+    long aSign = Long.signum(a);
+    long bSign = Long.signum(b);
+    if ((aSign != 0) && (bSign != 0) && (aSign == bSign)) {
+      if (aSign > 0) {
+        if (Long.MAX_VALUE - a < b)
+          return Long.MAX_VALUE;
+      } else {
+        if (Long.MIN_VALUE - a > b)
+          return Long.MIN_VALUE;
+      }
+    }
+    return a + b;
+  }
+  
+  /**
+   * A convenience method for setting the long encoding type.
+   * 
+   * @param is
+   *          IteratorSetting object to configure.
+   * @param type
+   *          LongCombiner.Type specifying the encoding type.
+   */
+  public static void setEncodingType(IteratorSetting is, LongCombiner.Type type) {
+    is.addOption(TYPE, type.toString());
+  }
+  
+  /**
+   * A convenience method for setting the long encoding type.
+   * 
+   * @param is
+   *          IteratorSetting object to configure.
+   * @param encoderClass
+   *          Class<? extends Encoder<Long>> specifying the encoding type.
+   */
+  public static void setEncodingType(IteratorSetting is, Class<? extends Encoder<Long>> encoderClass) {
+    is.addOption(TYPE, CLASS_PREFIX + encoderClass.getName());
+  }
+  
+  /**
+   * A convenience method for setting the long encoding type.
+   * 
+   * @param is
+   *          IteratorSetting object to configure.
+   * @param encoderClassName
+   *          name of a class specifying the encoding type.
+   */
+  public static void setEncodingType(IteratorSetting is, String encoderClassName) {
+    is.addOption(TYPE, CLASS_PREFIX + encoderClassName);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OptionDescriber.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OptionDescriber.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OptionDescriber.java
new file mode 100644
index 0000000..dad2fe2
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OptionDescriber.java
@@ -0,0 +1,128 @@
+/*
+ * 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.iterators;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The OptionDescriber interface allows you to set up iterator properties interactively in the accumulo shell. If your iterator and/or filter must implement
+ * this interface for the interactive part. The alternative would be to manually set configuration options with the config -t tableName property=value. If you
+ * go the manual route, be careful to use the correct structure for the property and to set all the properties required for the iterator.
+ * 
+ * OptionDescribers will need to implement two methods: {@code describeOptions()} which returns an instance of {@link IteratorOptions} and
+ * {@code validateOptions(Map<String,String> options)} which is intended to throw an exception or return false if the options are not acceptable.
+ * 
+ */
+public interface OptionDescriber {
+  public static class IteratorOptions {
+    public LinkedHashMap<String,String> namedOptions;
+    public ArrayList<String> unnamedOptionDescriptions;
+    public String name;
+    public String description;
+    
+    /**
+     * IteratorOptions holds the name, description, and option information for an iterator.
+     * 
+     * @param name
+     *          is the distinguishing name for the iterator or filter
+     * @param description
+     *          is a description of the iterator or filter
+     * @param namedOptions
+     *          is a map from specifically named options to their descriptions (null if unused) e.g., the AgeOffFilter requires a parameter called "ttl", so its
+     *          namedOptions = Collections.singletonMap("ttl", "time to live (milliseconds)")
+     * @param unnamedOptionDescriptions
+     *          is a list of descriptions of additional options that don't have fixed names (null if unused). The descriptions are intended to describe a
+     *          category, and the user will provide parameter names and values in that category; e.g., the FilteringIterator needs a list of Filters intended to
+     *          be named by their priority numbers, so its unnamedOptionDescriptions =
+     *          Collections.singletonList("<filterPriorityNumber> <ageoff|regex|filterClass>")
+     */
+    public IteratorOptions(String name, String description, Map<String,String> namedOptions, List<String> unnamedOptionDescriptions) {
+      this.name = name;
+      this.namedOptions = null;
+      if (namedOptions != null)
+        this.namedOptions = new LinkedHashMap<String,String>(namedOptions);
+      this.unnamedOptionDescriptions = null;
+      if (unnamedOptionDescriptions != null)
+        this.unnamedOptionDescriptions = new ArrayList<String>(unnamedOptionDescriptions);
+      this.description = description;
+    }
+    
+    public Map<String,String> getNamedOptions() {
+      return namedOptions;
+    }
+    
+    public List<String> getUnnamedOptionDescriptions() {
+      return unnamedOptionDescriptions;
+    }
+    
+    public String getName() {
+      return name;
+    }
+    
+    public String getDescription() {
+      return description;
+    }
+    
+    public void setNamedOptions(Map<String,String> namedOptions) {
+      this.namedOptions = new LinkedHashMap<String,String>(namedOptions);
+    }
+    
+    public void setUnnamedOptionDescriptions(List<String> unnamedOptionDescriptions) {
+      this.unnamedOptionDescriptions = new ArrayList<String>(unnamedOptionDescriptions);
+    }
+    
+    public void setName(String name) {
+      this.name = name;
+    }
+    
+    public void setDescription(String description) {
+      this.description = description;
+    }
+    
+    public void addNamedOption(String name, String description) {
+      if (namedOptions == null)
+        namedOptions = new LinkedHashMap<String,String>();
+      namedOptions.put(name, description);
+    }
+    
+    public void addUnnamedOption(String description) {
+      if (unnamedOptionDescriptions == null)
+        unnamedOptionDescriptions = new ArrayList<String>();
+      unnamedOptionDescriptions.add(description);
+    }
+  }
+  
+  /**
+   * Gets an iterator options object that contains information needed to configure this iterator. This object will be used by the accumulo shell to prompt the
+   * user to input the appropriate information.
+   * 
+   * @return an iterator options object
+   */
+  public IteratorOptions describeOptions();
+  
+  /**
+   * Check to see if an options map contains all options required by an iterator and that the option values are in the expected formats.
+   * 
+   * @param options
+   *          a map of option names to option values
+   * @return true if options are valid, false otherwise
+   */
+  public boolean validateOptions(Map<String,String> options);
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OrIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OrIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OrIterator.java
new file mode 100644
index 0000000..f92767f
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/OrIterator.java
@@ -0,0 +1,243 @@
+/*
+ * 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.iterators;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.PriorityQueue;
+
+import org.apache.accumulo.core.data.ArrayByteSequence;
+import org.apache.accumulo.core.data.ByteSequence;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.Text;
+import org.apache.log4j.Logger;
+
+/**
+ * An iterator that handles "OR" query constructs on the server side. This code has been adapted/merged from Heap and Multi Iterators.
+ */
+
+public class OrIterator implements SortedKeyValueIterator<Key,Value> {
+  
+  private TermSource currentTerm;
+  private ArrayList<TermSource> sources;
+  private PriorityQueue<TermSource> sorted = new PriorityQueue<TermSource>(5);
+  private static final Text nullText = new Text();
+  private static final Key nullKey = new Key();
+  
+  protected static final Logger log = Logger.getLogger(OrIterator.class);
+  
+  protected static class TermSource implements Comparable<TermSource> {
+    public SortedKeyValueIterator<Key,Value> iter;
+    public Text term;
+    public Collection<ByteSequence> seekColfams;
+    
+    public TermSource(TermSource other) {
+      this.iter = other.iter;
+      this.term = other.term;
+      this.seekColfams = other.seekColfams;
+    }
+    
+    public TermSource(SortedKeyValueIterator<Key,Value> iter, Text term) {
+      this.iter = iter;
+      this.term = term;
+      // The desired column families for this source is the term itself
+      this.seekColfams = Collections.<ByteSequence>singletonList(new ArrayByteSequence(term.getBytes(), 0, term.getLength()));
+    }
+    
+    public int compareTo(TermSource o) {
+      // NOTE: If your implementation can have more than one row in a tablet,
+      // you must compare row key here first, then column qualifier.
+      // NOTE2: A null check is not needed because things are only added to the
+      // sorted after they have been determined to be valid.
+      return this.iter.getTopKey().compareColumnQualifier(o.iter.getTopKey().getColumnQualifier());
+    }
+  }
+  
+  public OrIterator() {
+    this.sources = new ArrayList<TermSource>();
+  }
+  
+  private OrIterator(OrIterator other, IteratorEnvironment env) {
+    this.sources = new ArrayList<TermSource>();
+    
+    for (TermSource TS : other.sources)
+      this.sources.add(new TermSource(TS.iter.deepCopy(env), TS.term));
+  }
+  
+  @Override
+  public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
+    return new OrIterator(this, env);
+  }
+  
+  public void addTerm(SortedKeyValueIterator<Key,Value> source, Text term, IteratorEnvironment env) {
+    this.sources.add(new TermSource(source.deepCopy(env), term));
+  }
+  
+  @Override
+  final public void next() throws IOException {
+    
+    if (currentTerm == null)
+      return;
+    
+    // Advance currentTerm
+    currentTerm.iter.next();
+    
+    // See if currentTerm is still valid, remove if not
+    if (!(currentTerm.iter.hasTop()) || ((currentTerm.term != null) && (currentTerm.term.compareTo(currentTerm.iter.getTopKey().getColumnFamily()) != 0)))
+      currentTerm = null;
+    
+    // optimization.
+    // if size == 0, currentTerm is the only item left,
+    // OR there are no items left.
+    // In either case, we don't need to use the PriorityQueue
+    if (sorted.size() > 0) {
+      // sort the term back in
+      if (currentTerm != null)
+        sorted.add(currentTerm);
+      // and get the current top item out.
+      currentTerm = sorted.poll();
+    }
+  }
+  
+  @Override
+  public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
+    
+    // If sources.size is 0, there is nothing to process, so just return.
+    if (sources.size() == 0) {
+      currentTerm = null;
+      return;
+    }
+    
+    // Optimization for when there is only one term.
+    // Yes, this is lots of duplicate code, but the speed works...
+    // and we don't have a priority queue of size 0 or 1.
+    if (sources.size() == 1) {
+      
+      if (currentTerm == null)
+        currentTerm = sources.get(0);
+      Range newRange = null;
+      
+      if (range != null) {
+        if ((range.getStartKey() == null) || (range.getStartKey().getRow() == null))
+          newRange = range;
+        else {
+          Key newKey = null;
+          if (range.getStartKey().getColumnQualifier() == null)
+            newKey = new Key(range.getStartKey().getRow(), (currentTerm.term == null) ? nullText : currentTerm.term);
+          else
+            newKey = new Key(range.getStartKey().getRow(), (currentTerm.term == null) ? nullText : currentTerm.term, range.getStartKey().getColumnQualifier());
+          newRange = new Range((newKey == null) ? nullKey : newKey, true, range.getEndKey(), false);
+        }
+      }
+      currentTerm.iter.seek(newRange, currentTerm.seekColfams, true);
+      
+      // If there is no top key
+      // OR we are:
+      // 1) NOT an iterator
+      // 2) we have seeked into the next term (ie: seek man, get man001)
+      // then ignore it as a valid source
+      if (!(currentTerm.iter.hasTop()) || ((currentTerm.term != null) && (currentTerm.term.compareTo(currentTerm.iter.getTopKey().getColumnFamily()) != 0)))
+        currentTerm = null;
+      
+      // Otherwise, source is valid.
+      return;
+    }
+    
+    // Clear the PriorityQueue so that we can re-populate it.
+    sorted.clear();
+    
+    // This check is put in here to guard against the "initial seek"
+    // crashing us because the topkey term does not match.
+    // Note: It is safe to do the "sources.size() == 1" above
+    // because an Or must have at least two elements.
+    if (currentTerm == null) {
+      for (TermSource TS : sources) {
+        TS.iter.seek(range, TS.seekColfams, true);
+        
+        if ((TS.iter.hasTop()) && ((TS.term != null) && (TS.term.compareTo(TS.iter.getTopKey().getColumnFamily()) == 0)))
+          sorted.add(TS);
+      }
+      currentTerm = sorted.poll();
+      return;
+    }
+    
+    TermSource TS = null;
+    Iterator<TermSource> iter = sources.iterator();
+    // For each term, seek forward.
+    // if a hit is not found, delete it from future searches.
+    while (iter.hasNext()) {
+      TS = iter.next();
+      Range newRange = null;
+      
+      if (range != null) {
+        if ((range.getStartKey() == null) || (range.getStartKey().getRow() == null))
+          newRange = range;
+        else {
+          Key newKey = null;
+          if (range.getStartKey().getColumnQualifier() == null)
+            newKey = new Key(range.getStartKey().getRow(), (TS.term == null) ? nullText : TS.term);
+          else
+            newKey = new Key(range.getStartKey().getRow(), (TS.term == null) ? nullText : TS.term, range.getStartKey().getColumnQualifier());
+          newRange = new Range((newKey == null) ? nullKey : newKey, true, range.getEndKey(), false);
+        }
+      }
+      
+      // Seek only to the term for this source as a column family
+      TS.iter.seek(newRange, TS.seekColfams, true);
+      
+      // If there is no top key
+      // OR we are:
+      // 1) NOT an iterator
+      // 2) we have seeked into the next term (ie: seek man, get man001)
+      // then ignore it as a valid source
+      if (!(TS.iter.hasTop()) || ((TS.term != null) && (TS.term.compareTo(TS.iter.getTopKey().getColumnFamily()) != 0)))
+        iter.remove();
+      
+      // Otherwise, source is valid. Add it to the sources.
+      sorted.add(TS);
+    }
+    
+    // And set currentTerm = the next valid key/term.
+    currentTerm = sorted.poll();
+  }
+  
+  @Override
+  final public Key getTopKey() {
+    return currentTerm.iter.getTopKey();
+  }
+  
+  @Override
+  final public Value getTopValue() {
+    return currentTerm.iter.getTopValue();
+  }
+  
+  @Override
+  final public boolean hasTop() {
+    return currentTerm != null;
+  }
+  
+  @Override
+  public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
+    throw new UnsupportedOperationException();
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/RowDeletingIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/RowDeletingIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/RowDeletingIterator.java
new file mode 100644
index 0000000..60ccedd
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/RowDeletingIterator.java
@@ -0,0 +1,26 @@
+/**
+ * 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.iterators;
+
+/**
+ * This class remains here for backwards compatibility.
+ * 
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.RowDeletingIterator}
+ */
+public class RowDeletingIterator extends org.apache.accumulo.core.iterators.user.RowDeletingIterator {
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SkippingIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SkippingIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SkippingIterator.java
new file mode 100644
index 0000000..a73d997
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SkippingIterator.java
@@ -0,0 +1,41 @@
+/*
+ * 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.iterators;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.apache.accumulo.core.data.ByteSequence;
+import org.apache.accumulo.core.data.Range;
+
+public abstract class SkippingIterator extends WrappingIterator {
+  
+  @Override
+  public void next() throws IOException {
+    super.next();
+    consume();
+  }
+  
+  protected abstract void consume() throws IOException;
+  
+  @Override
+  public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
+    super.seek(range, columnFamilies, inclusive);
+    consume();
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyIterator.java
new file mode 100644
index 0000000..2bec869
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyIterator.java
@@ -0,0 +1,52 @@
+/*
+ * 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.iterators;
+
+import java.util.Map;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+
+public class SortedKeyIterator extends WrappingIterator implements OptionDescriber {
+  private static final Value NOVALUE = new Value(new byte[0]);
+  
+  public SortedKeyIterator() {}
+  
+  public SortedKeyIterator(SortedKeyIterator other, IteratorEnvironment env) {
+    setSource(other.getSource().deepCopy(env));
+  }
+  
+  @Override
+  public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
+    return new SortedKeyIterator(this, env);
+  }
+  
+  @Override
+  public Value getTopValue() {
+    return NOVALUE;
+  }
+  
+  @Override
+  public IteratorOptions describeOptions() {
+    return new IteratorOptions("keyset", SortedKeyIterator.class.getSimpleName() + " filters out values, but leaves keys intact", null, null);
+  }
+  
+  @Override
+  public boolean validateOptions(Map<String,String> options) {
+    return options == null || options.isEmpty();
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyValueIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyValueIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyValueIterator.java
new file mode 100644
index 0000000..6d38671
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedKeyValueIterator.java
@@ -0,0 +1,141 @@
+/*
+ * 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.iterators;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.apache.accumulo.core.data.ByteSequence;
+import org.apache.accumulo.core.data.Range;
+import org.apache.hadoop.io.Writable;
+import org.apache.hadoop.io.WritableComparable;
+
+/**
+ * An iterator that supports iterating over key and value pairs. Anything implementing this interface should return keys in sorted order.
+ */
+
+public interface SortedKeyValueIterator<K extends WritableComparable<?>,V extends Writable> {
+  /**
+   * Initializes the iterator. Data should not be read from the source in this method.
+   * 
+   * @param source
+   *          <tt>SortedKeyValueIterator</tt> source to read data from.
+   * @param options
+   *          <tt>Map</tt> map of string option names to option values.
+   * @param env
+   *          <tt>IteratorEnvironment</tt> environment in which iterator is being run.
+   * @throws IOException
+   *           unused.
+   * @exception IllegalArgumentException
+   *              if there are problems with the options.
+   * @exception UnsupportedOperationException
+   *              if not supported.
+   */
+  void init(SortedKeyValueIterator<K,V> source, Map<String,String> options, IteratorEnvironment env) throws IOException;
+  
+  /**
+   * Returns true if the iterator has more elements.
+   * 
+   * @return <tt>true</tt> if the iterator has more elements.
+   * @exception IllegalStateException
+   *              if called before seek.
+   */
+  boolean hasTop();
+  
+  /**
+   * Advances to the next K,V pair. Note that in minor compaction scope and in non-full major compaction scopes the iterator may see deletion entries. These
+   * entries should be preserved by all iterators except ones that are strictly scan-time iterators that will never be configured for the minc or majc scopes.
+   * Deletion entries are only removed during full major compactions.
+   * 
+   * @throws IOException
+   *           if an I/O error occurs.
+   * @exception IllegalStateException
+   *              if called before seek.
+   * @exception NoSuchElementException
+   *              if next element doesn't exist.
+   */
+  void next() throws IOException;
+  
+  /**
+   * Seeks to the first key in the Range, restricting the resulting K,V pairs to those with the specified columns. An iterator does not have to stop at the end
+   * of the range. The whole range is provided so that iterators can make optimizations.
+   * 
+   * Seek may be called multiple times with different parameters after {@link #init} is called.
+   * 
+   * Iterators that examine groups of adjacent key/value pairs (e.g. rows) to determine their top key and value should be sure that they properly handle a seek
+   * to a key in the middle of such a group (e.g. the middle of a row). Even if the client always seeks to a range containing an entire group (a,c), the tablet
+   * server could send back a batch of entries corresponding to (a,b], then reseek the iterator to range (b,c) when the scan is continued.
+   *
+   * {@code columnFamilies} is used, at the lowest level, to determine which data blocks inside of an RFile need to be opened for this iterator. This set of data
+   * blocks is also the set of locality groups defined for the given table. If no columnFamilies are provided, the data blocks for all locality groups inside of
+   * the correct RFile will be opened and seeked in an attempt to find the correct start key, irregardless of the startKey in the {@code range}.
+   *
+   * In an Accumulo instance in which multiple locality groups exist for a table, it is important to ensure that {@code columnFamilies} is properly set to the
+   * minimum required column families to ensure that data from separate locality groups is not inadvertently read.
+   * 
+   * @param range
+   *          <tt>Range</tt> of keys to iterate over.
+   * @param columnFamilies
+   *          <tt>Collection</tt> of column families to include or exclude.
+   * @param inclusive
+   *          <tt>boolean</tt> that indicates whether to include (true) or exclude (false) column families.
+   * @throws IOException
+   *           if an I/O error occurs.
+   * @exception IllegalArgumentException
+   *              if there are problems with the parameters.
+   */
+  void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException;
+  
+  /**
+   * Returns top key. Can be called 0 or more times without affecting behavior of next() or hasTop(). Note that in minor compaction scope and in non-full major
+   * compaction scopes the iterator may see deletion entries. These entries should be preserved by all iterators except ones that are strictly scan-time
+   * iterators that will never be configured for the minc or majc scopes. Deletion entries are only removed during full major compactions.
+   * 
+   * @return <tt>K</tt>
+   * @exception IllegalStateException
+   *              if called before seek.
+   * @exception NoSuchElementException
+   *              if top element doesn't exist.
+   */
+  K getTopKey();
+  
+  /**
+   * Returns top value. Can be called 0 or more times without affecting behavior of next() or hasTop().
+   * 
+   * @return <tt>V</tt>
+   * @exception IllegalStateException
+   *              if called before seek.
+   * @exception NoSuchElementException
+   *              if top element doesn't exist.
+   */
+  V getTopValue();
+  
+  /**
+   * Creates a deep copy of this iterator as though seek had not yet been called. init should be called on an iterator before deepCopy is called. init should
+   * not need to be called on the copy that is returned by deepCopy; that is, when necessary init should be called in the deepCopy method on the iterator it
+   * returns. The behavior is unspecified if init is called after deepCopy either on the original or the copy.
+   * 
+   * @param env
+   *          <tt>IteratorEnvironment</tt> environment in which iterator is being run.
+   * @return <tt>SortedKeyValueIterator</tt> a copy of this iterator (with the same source and settings).
+   * @exception UnsupportedOperationException
+   *              if not supported.
+   */
+  SortedKeyValueIterator<K,V> deepCopy(IteratorEnvironment env);
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedMapIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedMapIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedMapIterator.java
new file mode 100644
index 0000000..8928bb2
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/SortedMapIterator.java
@@ -0,0 +1,135 @@
+/*
+ * 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.iterators;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.accumulo.core.data.ByteSequence;
+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.iterators.system.InterruptibleIterator;
+
+/**
+ * A simple iterator over a Java SortedMap
+ * 
+ * 
+ */
+
+public class SortedMapIterator implements InterruptibleIterator {
+  private Iterator<Entry<Key,Value>> iter;
+  private Entry<Key,Value> entry;
+  
+  private SortedMap<Key,Value> map;
+  private Range range;
+  
+  private AtomicBoolean interruptFlag;
+  private int interruptCheckCount = 0;
+  
+  public SortedMapIterator deepCopy(IteratorEnvironment env) {
+    return new SortedMapIterator(map, interruptFlag);
+  }
+  
+  private SortedMapIterator(SortedMap<Key,Value> map, AtomicBoolean interruptFlag) {
+    this.map = map;
+    iter = null;
+    this.range = new Range();
+    entry = null;
+    
+    this.interruptFlag = interruptFlag;
+  }
+  
+  public SortedMapIterator(SortedMap<Key,Value> map) {
+    this(map, null);
+  }
+  
+  @Override
+  public Key getTopKey() {
+    return entry.getKey();
+  }
+  
+  @Override
+  public Value getTopValue() {
+    return entry.getValue();
+  }
+  
+  @Override
+  public boolean hasTop() {
+    return entry != null;
+  }
+  
+  @Override
+  public void next() throws IOException {
+    
+    if (entry == null)
+      throw new IllegalStateException();
+    
+    if (interruptFlag != null && interruptCheckCount++ % 100 == 0 && interruptFlag.get())
+      throw new IterationInterruptedException();
+    
+    if (iter.hasNext()) {
+      entry = iter.next();
+      if (range.afterEndKey((Key) entry.getKey())) {
+        entry = null;
+      }
+    } else
+      entry = null;
+    
+  }
+  
+  @Override
+  public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
+    
+    if (interruptFlag != null && interruptFlag.get())
+      throw new IterationInterruptedException();
+    
+    this.range = range;
+    
+    Key key = range.getStartKey();
+    if (key == null) {
+      key = new Key();
+    }
+    
+    iter = map.tailMap(key).entrySet().iterator();
+    if (iter.hasNext()) {
+      entry = iter.next();
+      if (range.afterEndKey(entry.getKey())) {
+        entry = null;
+      }
+    } else
+      entry = null;
+    
+    while (hasTop() && range.beforeStartKey(getTopKey())) {
+      next();
+    }
+  }
+  
+  public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
+    throw new UnsupportedOperationException();
+  }
+  
+  @Override
+  public void setInterruptFlag(AtomicBoolean flag) {
+    this.interruptFlag = flag;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/TypedValueCombiner.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/TypedValueCombiner.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/TypedValueCombiner.java
new file mode 100644
index 0000000..126c8fb
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/TypedValueCombiner.java
@@ -0,0 +1,244 @@
+/*
+ * 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.iterators;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.start.classloader.AccumuloClassLoader;
+
+/**
+ * A Combiner that decodes each Value to type V before reducing, then encodes the result of typedReduce back to Value.
+ * 
+ * Subclasses must implement a typedReduce method: public V typedReduce(Key key, Iterator<V> iter);
+ * 
+ * This typedReduce method will be passed the most recent Key and an iterator over the Values (translated to Vs) for all non-deleted versions of that Key.
+ * 
+ * Subclasses may implement a switch on the "type" variable to choose an Encoder in their init method.
+ */
+public abstract class TypedValueCombiner<V> extends Combiner {
+  private Encoder<V> encoder = null;
+  private boolean lossy = false;
+  
+  protected static final String LOSSY = "lossy";
+  
+  /**
+   * A Java Iterator that translates an Iterator<Value> to an Iterator<V> using the decode method of an Encoder.
+   */
+  private static class VIterator<V> implements Iterator<V> {
+    private Iterator<Value> source;
+    private Encoder<V> encoder;
+    private boolean lossy;
+    
+    /**
+     * Constructs an Iterator<V> from an Iterator<Value>
+     * 
+     * @param iter
+     *          The source iterator
+     * 
+     * @param encoder
+     *          The Encoder whose decode method is used to translate from Value to V
+     * 
+     * @param lossy
+     *          Determines whether to error on failure to decode or ignore and move on
+     */
+    VIterator(Iterator<Value> iter, Encoder<V> encoder, boolean lossy) {
+      this.source = iter;
+      this.encoder = encoder;
+      this.lossy = lossy;
+    }
+    
+    V next = null;
+    boolean hasNext = false;
+    
+    @Override
+    public boolean hasNext() {
+      if (hasNext)
+        return true;
+      
+      while (true) {
+        if (!source.hasNext())
+          return false;
+        try {
+          next = encoder.decode(source.next().get());
+          return hasNext = true;
+        } catch (ValueFormatException vfe) {
+          if (!lossy)
+            throw vfe;
+        }
+      }
+    }
+    
+    @Override
+    public V next() {
+      if (!hasNext && !hasNext())
+        throw new NoSuchElementException();
+      V toRet = next;
+      next = null;
+      hasNext = false;
+      return toRet;
+    }
+    
+    @Override
+    public void remove() {
+      source.remove();
+    }
+  }
+  
+  /**
+   * An interface for translating from byte[] to V and back.
+   */
+  public static interface Encoder<V> {
+    public byte[] encode(V v);
+    
+    public V decode(byte[] b) throws ValueFormatException;
+  }
+  
+  /**
+   * Sets the Encoder<V> used to translate Values to V and back.
+   * 
+   * @param encoder
+   */
+  protected void setEncoder(Encoder<V> encoder) {
+    this.encoder = encoder;
+  }
+  
+  /**
+   * Instantiates and sets the Encoder<V> used to translate Values to V and back.
+   * 
+   * @param encoderClass
+   * @throws IllegalArgumentException
+   *           if ClassNotFoundException, InstantiationException, or IllegalAccessException occurs
+   */
+  protected void setEncoder(String encoderClass) {
+    try {
+      @SuppressWarnings("unchecked")
+      Class<? extends Encoder<V>> clazz = (Class<? extends Encoder<V>>) AccumuloClassLoader.loadClass(encoderClass, Encoder.class);
+      encoder = clazz.newInstance();
+    } catch (ClassNotFoundException e) {
+      throw new IllegalArgumentException(e);
+    } catch (InstantiationException e) {
+      throw new IllegalArgumentException(e);
+    } catch (IllegalAccessException e) {
+      throw new IllegalArgumentException(e);
+    }
+  }
+  
+  /**
+   * Tests whether v remains the same when encoded and decoded with the current encoder.
+   * 
+   * @param v
+   * @throws IllegalStateException
+   *           if an encoder has not been set.
+   * @throws IllegalArgumentException
+   *           if the test fails.
+   */
+  protected void testEncoder(V v) {
+    if (encoder == null)
+      throw new IllegalStateException("encoder has not been initialized");
+    testEncoder(encoder, v);
+  }
+  
+  /**
+   * Tests whether v remains the same when encoded and decoded with the given encoder.
+   * 
+   * @param encoder
+   * @param v
+   * @throws IllegalArgumentException
+   *           if the test fails.
+   */
+  public static <V> void testEncoder(Encoder<V> encoder, V v) {
+    try {
+      if (!v.equals(encoder.decode(encoder.encode(v))))
+        throw new IllegalArgumentException("something wrong with " + encoder.getClass().getName() + " -- doesn't encode and decode " + v + " properly");
+    } catch (ClassCastException e) {
+      throw new IllegalArgumentException(encoder.getClass().getName() + " doesn't encode " + v.getClass().getName());
+    }
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Override
+  public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
+    TypedValueCombiner<V> newInstance = (TypedValueCombiner<V>) super.deepCopy(env);
+    newInstance.setEncoder(encoder);
+    return newInstance;
+  }
+  
+  @Override
+  public Value reduce(Key key, Iterator<Value> iter) {
+    return new Value(encoder.encode(typedReduce(key, new VIterator<V>(iter, encoder, lossy))));
+  }
+  
+  @Override
+  public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
+    super.init(source, options, env);
+    setLossyness(options);
+  }
+  
+  private void setLossyness(Map<String,String> options) {
+    String loss = options.get(LOSSY);
+    if (loss == null)
+      lossy = false;
+    else
+      lossy = Boolean.parseBoolean(loss);
+  }
+  
+  @Override
+  public IteratorOptions describeOptions() {
+    IteratorOptions io = super.describeOptions();
+    io.addNamedOption(LOSSY, "if true, failed decodes are ignored. Otherwise combiner will error on failed decodes (default false): <TRUE|FALSE>");
+    return io;
+  }
+  
+  @Override
+  public boolean validateOptions(Map<String,String> options) {
+    super.validateOptions(options);
+    setLossyness(options);
+    return true;
+  }
+  
+  /**
+   * A convenience method to set the "lossy" option on a TypedValueCombiner. If true, the combiner will ignore any values which fail to decode. Otherwise, the
+   * combiner will throw an error which will interrupt the action (and prevent potential data loss). False is the default behavior.
+   * 
+   * @param is
+   *          iterator settings object to configure
+   * @param lossy
+   *          if true the combiner will ignored values which fail to decode; otherwise error.
+   */
+  public static void setLossyness(IteratorSetting is, boolean lossy) {
+    is.addOption(LOSSY, Boolean.toString(lossy));
+  }
+  
+  /**
+   * Reduces a list of V into a single V.
+   * 
+   * @param key
+   *          The most recent version of the Key being reduced.
+   * 
+   * @param iter
+   *          An iterator over the V for different versions of the key.
+   * 
+   * @return The combined V.
+   */
+  public abstract V typedReduce(Key key, Iterator<V> iter);
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/ValueFormatException.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/ValueFormatException.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/ValueFormatException.java
new file mode 100644
index 0000000..83bfb57
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/ValueFormatException.java
@@ -0,0 +1,40 @@
+/**
+ * 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.iterators;
+
+/**
+ * Exception used for TypedValueCombiner and it's Encoders decode() function
+ */
+public class ValueFormatException extends IllegalArgumentException {
+  
+  /**
+   * @param string
+   */
+  public ValueFormatException(String string) {
+    super(string);
+  }
+
+  /**
+   * @param nfe
+   */
+  public ValueFormatException(Exception nfe) {
+    super(nfe);
+  }
+
+  private static final long serialVersionUID = 4170291568272971821L;
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/VersioningIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/VersioningIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/VersioningIterator.java
new file mode 100644
index 0000000..38f56ca
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/VersioningIterator.java
@@ -0,0 +1,35 @@
+/*
+ * 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.iterators;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * This class remains here for backwards compatibility.
+ * 
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.VersioningIterator}
+ */
+public class VersioningIterator extends org.apache.accumulo.core.iterators.user.VersioningIterator {
+  public VersioningIterator() {}
+  
+  public VersioningIterator(SortedKeyValueIterator<Key,Value> iterator, int maxVersions) {
+    super();
+    this.setSource(iterator);
+    this.maxVersions = maxVersions;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WholeRowIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WholeRowIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WholeRowIterator.java
new file mode 100644
index 0000000..0ea97a0
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WholeRowIterator.java
@@ -0,0 +1,26 @@
+/**
+ * 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.iterators;
+
+/**
+ * This class remains here for backwards compatibility.
+ * 
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.WholeRowIterator}
+ */
+public class WholeRowIterator extends org.apache.accumulo.core.iterators.user.WholeRowIterator {
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WrappingIterator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WrappingIterator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WrappingIterator.java
new file mode 100644
index 0000000..060fa76
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/WrappingIterator.java
@@ -0,0 +1,105 @@
+/*
+ * 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.iterators;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.accumulo.core.data.ByteSequence;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * A convenience class for implementing iterators that select, but do not modify, entries read from a source iterator. Default implementations exist for all
+ * methods, but {@link #deepCopy} will throw an <code>UnsupportedOperationException</code>.
+ * 
+ * This iterator has some checks in place to enforce the iterator contract. Specifically, it verifies that it has a source iterator and that {@link #seek} has
+ * been called before any data is read. If either of these conditions does not hold true, an <code>IllegalStateException</code> will be thrown. In particular,
+ * this means that <code>getSource().seek</code> and <code>super.seek</code> no longer perform identical actions. Implementors should take note of this and if
+ * <code>seek</code> is overridden, ensure that <code>super.seek</code> is called before data is read.
+ */
+public abstract class WrappingIterator implements SortedKeyValueIterator<Key,Value> {
+  
+  private SortedKeyValueIterator<Key,Value> source = null;
+  boolean seenSeek = false;
+  
+  protected void setSource(SortedKeyValueIterator<Key,Value> source) {
+    this.source = source;
+  }
+  
+  protected SortedKeyValueIterator<Key,Value> getSource() {
+    if (source == null)
+      throw new IllegalStateException("getting null source");
+    return source;
+  }
+  
+  @Override
+  public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
+    throw new UnsupportedOperationException();
+  }
+  
+  @Override
+  public Key getTopKey() {
+    if (source == null)
+      throw new IllegalStateException("no source set");
+    if (seenSeek == false)
+      throw new IllegalStateException("never been seeked");
+    return getSource().getTopKey();
+  }
+  
+  @Override
+  public Value getTopValue() {
+    if (source == null)
+      throw new IllegalStateException("no source set");
+    if (seenSeek == false)
+      throw new IllegalStateException("never been seeked");
+    return getSource().getTopValue();
+  }
+  
+  @Override
+  public boolean hasTop() {
+    if (source == null)
+      throw new IllegalStateException("no source set");
+    if (seenSeek == false)
+      throw new IllegalStateException("never been seeked");
+    return getSource().hasTop();
+  }
+  
+  @Override
+  public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
+    this.setSource(source);
+    
+  }
+  
+  @Override
+  public void next() throws IOException {
+    if (source == null)
+      throw new IllegalStateException("no source set");
+    if (seenSeek == false)
+      throw new IllegalStateException("never been seeked");
+    getSource().next();
+  }
+  
+  @Override
+  public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
+    getSource().seek(range, columnFamilies, inclusive);
+    seenSeek = true;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/Aggregator.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/Aggregator.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/Aggregator.java
new file mode 100644
index 0000000..83f0f39
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/Aggregator.java
@@ -0,0 +1,30 @@
+/*
+ * 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.iterators.aggregation;
+
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.Combiner}
+ */
+public interface Aggregator {
+  void reset();
+  
+  void collect(Value value);
+  
+  Value aggregate();
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/LongSummation.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/LongSummation.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/LongSummation.java
new file mode 100644
index 0000000..3da9a01
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/LongSummation.java
@@ -0,0 +1,71 @@
+/*
+ * 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.iterators.aggregation;
+
+import java.io.IOException;
+
+import org.apache.accumulo.core.data.Value;
+import org.apache.log4j.Logger;
+
+/**
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.SummingCombiner} with
+ *             {@link org.apache.accumulo.core.iterators.LongCombiner.Type#FIXEDLEN}
+ */
+public class LongSummation implements Aggregator {
+  private static final Logger log = Logger.getLogger(LongSummation.class);
+  long sum = 0;
+  
+  public Value aggregate() {
+    return new Value(longToBytes(sum));
+  }
+  
+  public void collect(Value value) {
+    try {
+      sum += bytesToLong(value.get());
+    } catch (IOException e) {
+      log.error(LongSummation.class.getSimpleName() + " trying to convert bytes to long, but byte array isn't length 8");
+    }
+  }
+  
+  public void reset() {
+    sum = 0;
+  }
+  
+  public static long bytesToLong(byte[] b) throws IOException {
+    return bytesToLong(b, 0);
+  }
+  
+  public static long bytesToLong(byte[] b, int offset) throws IOException {
+    if (b.length < offset + 8)
+      throw new IOException("trying to convert to long, but byte array isn't long enough, wanted " + (offset + 8) + " found " + b.length);
+    return (((long) b[offset + 0] << 56) + ((long) (b[offset + 1] & 255) << 48) + ((long) (b[offset + 2] & 255) << 40) + ((long) (b[offset + 3] & 255) << 32)
+        + ((long) (b[offset + 4] & 255) << 24) + ((b[offset + 5] & 255) << 16) + ((b[offset + 6] & 255) << 8) + ((b[offset + 7] & 255) << 0));
+  }
+  
+  public static byte[] longToBytes(long l) {
+    byte[] b = new byte[8];
+    b[0] = (byte) (l >>> 56);
+    b[1] = (byte) (l >>> 48);
+    b[2] = (byte) (l >>> 40);
+    b[3] = (byte) (l >>> 32);
+    b[4] = (byte) (l >>> 24);
+    b[5] = (byte) (l >>> 16);
+    b[6] = (byte) (l >>> 8);
+    b[7] = (byte) (l >>> 0);
+    return b;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumArraySummation.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumArraySummation.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumArraySummation.java
new file mode 100644
index 0000000..6a93f22
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumArraySummation.java
@@ -0,0 +1,92 @@
+/*
+ * 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.iterators.aggregation;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.WritableUtils;
+
+/**
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.SummingArrayCombiner} with
+ *             {@link org.apache.accumulo.core.iterators.user.SummingArrayCombiner.Type#VARLEN}
+ */
+public class NumArraySummation implements Aggregator {
+  long[] sum = new long[0];
+  
+  public Value aggregate() {
+    try {
+      return new Value(NumArraySummation.longArrayToBytes(sum));
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  
+  public void collect(Value value) {
+    long[] la;
+    try {
+      la = NumArraySummation.bytesToLongArray(value.get());
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    
+    if (la.length > sum.length) {
+      for (int i = 0; i < sum.length; i++) {
+        la[i] = NumSummation.safeAdd(la[i], sum[i]);
+      }
+      sum = la;
+    } else {
+      for (int i = 0; i < la.length; i++) {
+        sum[i] = NumSummation.safeAdd(sum[i], la[i]);
+      }
+    }
+  }
+  
+  public static byte[] longArrayToBytes(long[] la) throws IOException {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    DataOutputStream dos = new DataOutputStream(baos);
+    
+    WritableUtils.writeVInt(dos, la.length);
+    for (int i = 0; i < la.length; i++) {
+      WritableUtils.writeVLong(dos, la[i]);
+    }
+    
+    return baos.toByteArray();
+  }
+  
+  public static long[] bytesToLongArray(byte[] b) throws IOException {
+    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(b));
+    int len = WritableUtils.readVInt(dis);
+    
+    long[] la = new long[len];
+    
+    for (int i = 0; i < len; i++) {
+      la[i] = WritableUtils.readVLong(dis);
+    }
+    
+    return la;
+  }
+  
+  public void reset() {
+    sum = new long[0];
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumSummation.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumSummation.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumSummation.java
new file mode 100644
index 0000000..2fa6026
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/NumSummation.java
@@ -0,0 +1,87 @@
+/*
+ * 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.iterators.aggregation;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.WritableUtils;
+
+/**
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.SummingCombiner} with
+ *             {@link org.apache.accumulo.core.iterators.LongCombiner.Type#VARLEN}
+ */
+public class NumSummation implements Aggregator {
+  long sum = 0l;
+  
+  public Value aggregate() {
+    try {
+      return new Value(NumSummation.longToBytes(sum));
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  
+  public void collect(Value value) {
+    long l;
+    try {
+      l = NumSummation.bytesToLong(value.get());
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    
+    sum = NumSummation.safeAdd(sum, l);
+  }
+  
+  public static byte[] longToBytes(long l) throws IOException {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    DataOutputStream dos = new DataOutputStream(baos);
+    
+    WritableUtils.writeVLong(dos, l);
+    
+    return baos.toByteArray();
+  }
+  
+  public static long bytesToLong(byte[] b) throws IOException {
+    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(b));
+    return WritableUtils.readVLong(dis);
+  }
+  
+  public static long safeAdd(long a, long b) {
+    long aSign = Long.signum(a);
+    long bSign = Long.signum(b);
+    if ((aSign != 0) && (bSign != 0) && (aSign == bSign)) {
+      if (aSign > 0) {
+        if (Long.MAX_VALUE - a < b)
+          return Long.MAX_VALUE;
+      } else {
+        if (Long.MIN_VALUE - a > b)
+          return Long.MIN_VALUE;
+      }
+    }
+    return a + b;
+  }
+  
+  public void reset() {
+    sum = 0l;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMax.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMax.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMax.java
new file mode 100644
index 0000000..f066f7c
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMax.java
@@ -0,0 +1,44 @@
+/*
+ * 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.iterators.aggregation;
+
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.MaxCombiner} with
+ *             {@link org.apache.accumulo.core.iterators.LongCombiner.Type#STRING}
+ */
+public class StringMax implements Aggregator {
+  
+  long max = Long.MIN_VALUE;
+  
+  public Value aggregate() {
+    return new Value(Long.toString(max).getBytes());
+  }
+  
+  public void collect(Value value) {
+    long l = Long.parseLong(new String(value.get()));
+    if (l > max) {
+      max = l;
+    }
+  }
+  
+  public void reset() {
+    max = Long.MIN_VALUE;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMin.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMin.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMin.java
new file mode 100644
index 0000000..a712c2c
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringMin.java
@@ -0,0 +1,44 @@
+/*
+ * 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.iterators.aggregation;
+
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.MinCombiner} with
+ *             {@link org.apache.accumulo.core.iterators.LongCombiner.Type#STRING}
+ */
+public class StringMin implements Aggregator {
+  
+  long min = Long.MAX_VALUE;
+  
+  public Value aggregate() {
+    return new Value(Long.toString(min).getBytes());
+  }
+  
+  public void collect(Value value) {
+    long l = Long.parseLong(new String(value.get()));
+    if (l < min) {
+      min = l;
+    }
+  }
+  
+  public void reset() {
+    min = Long.MAX_VALUE;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringSummation.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringSummation.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringSummation.java
new file mode 100644
index 0000000..b2f8520
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/StringSummation.java
@@ -0,0 +1,41 @@
+/*
+ * 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.iterators.aggregation;
+
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * @deprecated since 1.4, replaced by {@link org.apache.accumulo.core.iterators.user.SummingCombiner} with
+ *             {@link org.apache.accumulo.core.iterators.LongCombiner.Type#STRING}
+ */
+public class StringSummation implements Aggregator {
+  
+  long sum = 0;
+  
+  public Value aggregate() {
+    return new Value(Long.toString(sum).getBytes());
+  }
+  
+  public void collect(Value value) {
+    sum += Long.parseLong(new String(value.get()));
+  }
+  
+  public void reset() {
+    sum = 0;
+    
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorConfiguration.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorConfiguration.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorConfiguration.java
new file mode 100644
index 0000000..403df09
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * 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.iterators.aggregation.conf;
+
+import org.apache.accumulo.core.iterators.conf.PerColumnIteratorConfig;
+import org.apache.hadoop.io.Text;
+
+/**
+ * @deprecated since 1.4
+ */
+public class AggregatorConfiguration extends PerColumnIteratorConfig {
+  
+  public AggregatorConfiguration(Text columnFamily, String aggClassName) {
+    super(columnFamily, aggClassName);
+  }
+  
+  public AggregatorConfiguration(Text columnFamily, Text columnQualifier, String aggClassName) {
+    super(columnFamily, columnQualifier, aggClassName);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7bdbfccb/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorSet.java
----------------------------------------------------------------------
diff --git a/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorSet.java b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorSet.java
new file mode 100644
index 0000000..9e9e7e1
--- /dev/null
+++ b/1.5/core/src/main/java/org/apache/accumulo/core/iterators/aggregation/conf/AggregatorSet.java
@@ -0,0 +1,40 @@
+/*
+ * 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.iterators.aggregation.conf;
+
+import java.util.Map;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.iterators.aggregation.Aggregator;
+import org.apache.accumulo.core.iterators.conf.ColumnToClassMapping;
+
+/**
+ * @deprecated since 1.4
+ */
+public class AggregatorSet extends ColumnToClassMapping<Aggregator> {
+  public AggregatorSet(Map<String,String> opts) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+    super(opts, Aggregator.class);
+  }
+  
+  public AggregatorSet() {
+    super();
+  }
+  
+  public Aggregator getAggregator(Key k) {
+    return getObject(k);
+  }
+}


Mime
View raw message