You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2009/05/22 17:33:44 UTC

svn commit: r777578 [1/2] - in /incubator/cassandra/trunk: interface/ interface/gen-java/org/apache/cassandra/service/ lib/ src/java/org/apache/cassandra/db/ src/java/org/apache/cassandra/io/ src/java/org/apache/cassandra/service/ src/java/org/apache/c...

Author: jbellis
Date: Fri May 22 15:33:42 2009
New Revision: 777578

URL: http://svn.apache.org/viewvc?rev=777578&view=rev
Log:
Add get_slice_from functionality using column indexes for efficiency.
Patch by Jun Rao and jbellis for CASSANDRA-172

Added:
    incubator/cassandra/trunk/lib/google-collect-1.0-rc1.jar
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/SliceFromReadCommand.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/utils/ReducingIterator.java
Modified:
    incubator/cassandra/trunk/interface/cassandra.thrift
    incubator/cassandra/trunk/interface/gen-java/org/apache/cassandra/service/Cassandra.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnComparatorFactory.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/FileStruct.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ReadCommand.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTable.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SequenceFile.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/service/CassandraServer.java
    incubator/cassandra/trunk/test/unit/org/apache/cassandra/db/TableTest.java

Modified: incubator/cassandra/trunk/interface/cassandra.thrift
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/interface/cassandra.thrift?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/interface/cassandra.thrift (original)
+++ incubator/cassandra/trunk/interface/cassandra.thrift Fri May 22 15:33:42 2009
@@ -83,9 +83,12 @@
   list<column_t> get_slice_by_name_range(1:string tablename, 2:string key, 3:string columnFamily, 4:string start, 5:string end, 6:i32 count=-1)
   throws (1: InvalidRequestException ire, 2: NotFoundException nfe),
   
-list<column_t> get_slice_by_names(1:string tablename, 2:string key, 3:string columnFamily, 4:list<string> columnNames)
+  list<column_t> get_slice_by_names(1:string tablename, 2:string key, 3:string columnFamily, 4:list<string> columnNames)
   throws (1: InvalidRequestException ire, 2: NotFoundException nfe),
   
+  list<column_t> get_slice_from(1:string tablename, 2:string key, 3:string columnFamily_column, 4:bool isAscending, 5:i32 count)
+  throws (1: InvalidRequestException ire, 2: NotFoundException nfe),
+
   column_t       get_column(1:string tablename, 2:string key, 3:string columnFamily_column)
   throws (1: InvalidRequestException ire, 2: NotFoundException nfe),
 

Modified: incubator/cassandra/trunk/interface/gen-java/org/apache/cassandra/service/Cassandra.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/interface/gen-java/org/apache/cassandra/service/Cassandra.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/interface/gen-java/org/apache/cassandra/service/Cassandra.java (original)
+++ incubator/cassandra/trunk/interface/gen-java/org/apache/cassandra/service/Cassandra.java Fri May 22 15:33:42 2009
@@ -28,6 +28,8 @@
 
     public List<column_t> get_slice_by_names(String tablename, String key, String columnFamily, List<String> columnNames) throws InvalidRequestException, NotFoundException, TException;
 
+    public List<column_t> get_slice_from(String tablename, String key, String columnFamily_column, boolean isAscending, int count) throws InvalidRequestException, NotFoundException, TException;
+
     public column_t get_column(String tablename, String key, String columnFamily_column) throws InvalidRequestException, NotFoundException, TException;
 
     public int get_column_count(String tablename, String key, String columnFamily_column) throws InvalidRequestException, TException;
@@ -218,6 +220,49 @@
       throw new TApplicationException(TApplicationException.MISSING_RESULT, "get_slice_by_names failed: unknown result");
     }
 
+    public List<column_t> get_slice_from(String tablename, String key, String columnFamily_column, boolean isAscending, int count) throws InvalidRequestException, NotFoundException, TException
+    {
+      send_get_slice_from(tablename, key, columnFamily_column, isAscending, count);
+      return recv_get_slice_from();
+    }
+
+    public void send_get_slice_from(String tablename, String key, String columnFamily_column, boolean isAscending, int count) throws TException
+    {
+      oprot_.writeMessageBegin(new TMessage("get_slice_from", TMessageType.CALL, seqid_));
+      get_slice_from_args args = new get_slice_from_args();
+      args.tablename = tablename;
+      args.key = key;
+      args.columnFamily_column = columnFamily_column;
+      args.isAscending = isAscending;
+      args.count = count;
+      args.write(oprot_);
+      oprot_.writeMessageEnd();
+      oprot_.getTransport().flush();
+    }
+
+    public List<column_t> recv_get_slice_from() throws InvalidRequestException, NotFoundException, TException
+    {
+      TMessage msg = iprot_.readMessageBegin();
+      if (msg.type == TMessageType.EXCEPTION) {
+        TApplicationException x = TApplicationException.read(iprot_);
+        iprot_.readMessageEnd();
+        throw x;
+      }
+      get_slice_from_result result = new get_slice_from_result();
+      result.read(iprot_);
+      iprot_.readMessageEnd();
+      if (result.isSetSuccess()) {
+        return result.success;
+      }
+      if (result.ire != null) {
+        throw result.ire;
+      }
+      if (result.nfe != null) {
+        throw result.nfe;
+      }
+      throw new TApplicationException(TApplicationException.MISSING_RESULT, "get_slice_from failed: unknown result");
+    }
+
     public column_t get_column(String tablename, String key, String columnFamily_column) throws InvalidRequestException, NotFoundException, TException
     {
       send_get_column(tablename, key, columnFamily_column);
@@ -810,6 +855,7 @@
       processMap_.put("get_slice", new get_slice());
       processMap_.put("get_slice_by_name_range", new get_slice_by_name_range());
       processMap_.put("get_slice_by_names", new get_slice_by_names());
+      processMap_.put("get_slice_from", new get_slice_from());
       processMap_.put("get_column", new get_column());
       processMap_.put("get_column_count", new get_column_count());
       processMap_.put("insert", new insert());
@@ -943,6 +989,36 @@
 
     }
 
+    private class get_slice_from implements ProcessFunction {
+      public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException
+      {
+        get_slice_from_args args = new get_slice_from_args();
+        args.read(iprot);
+        iprot.readMessageEnd();
+        get_slice_from_result result = new get_slice_from_result();
+        try {
+          result.success = iface_.get_slice_from(args.tablename, args.key, args.columnFamily_column, args.isAscending, args.count);
+        } catch (InvalidRequestException ire) {
+          result.ire = ire;
+        } catch (NotFoundException nfe) {
+          result.nfe = nfe;
+        } catch (Throwable th) {
+          LOGGER.error("Internal error processing get_slice_from", th);
+          TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR, "Internal error processing get_slice_from");
+          oprot.writeMessageBegin(new TMessage("get_slice_from", TMessageType.EXCEPTION, seqid));
+          x.write(oprot);
+          oprot.writeMessageEnd();
+          oprot.getTransport().flush();
+          return;
+        }
+        oprot.writeMessageBegin(new TMessage("get_slice_from", TMessageType.REPLY, seqid));
+        result.write(oprot);
+        oprot.writeMessageEnd();
+        oprot.getTransport().flush();
+      }
+
+    }
+
     private class get_column implements ProcessFunction {
       public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException
       {
@@ -3310,57 +3386,915 @@
       this.columnFamily = columnFamily;
     }
 
-    public void unsetColumnFamily() {
-      this.columnFamily = null;
+    public void unsetColumnFamily() {
+      this.columnFamily = null;
+    }
+
+    // Returns true if field columnFamily is set (has been asigned a value) and false otherwise
+    public boolean isSetColumnFamily() {
+      return this.columnFamily != null;
+    }
+
+    public void setColumnFamilyIsSet(boolean value) {
+      if (!value) {
+        this.columnFamily = null;
+      }
+    }
+
+    public int getColumnNamesSize() {
+      return (this.columnNames == null) ? 0 : this.columnNames.size();
+    }
+
+    public java.util.Iterator<String> getColumnNamesIterator() {
+      return (this.columnNames == null) ? null : this.columnNames.iterator();
+    }
+
+    public void addToColumnNames(String elem) {
+      if (this.columnNames == null) {
+        this.columnNames = new ArrayList<String>();
+      }
+      this.columnNames.add(elem);
+    }
+
+    public List<String> getColumnNames() {
+      return this.columnNames;
+    }
+
+    public void setColumnNames(List<String> columnNames) {
+      this.columnNames = columnNames;
+    }
+
+    public void unsetColumnNames() {
+      this.columnNames = null;
+    }
+
+    // Returns true if field columnNames is set (has been asigned a value) and false otherwise
+    public boolean isSetColumnNames() {
+      return this.columnNames != null;
+    }
+
+    public void setColumnNamesIsSet(boolean value) {
+      if (!value) {
+        this.columnNames = null;
+      }
+    }
+
+    public void setFieldValue(int fieldID, Object value) {
+      switch (fieldID) {
+      case TABLENAME:
+        if (value == null) {
+          unsetTablename();
+        } else {
+          setTablename((String)value);
+        }
+        break;
+
+      case KEY:
+        if (value == null) {
+          unsetKey();
+        } else {
+          setKey((String)value);
+        }
+        break;
+
+      case COLUMNFAMILY:
+        if (value == null) {
+          unsetColumnFamily();
+        } else {
+          setColumnFamily((String)value);
+        }
+        break;
+
+      case COLUMNNAMES:
+        if (value == null) {
+          unsetColumnNames();
+        } else {
+          setColumnNames((List<String>)value);
+        }
+        break;
+
+      default:
+        throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
+      }
+    }
+
+    public Object getFieldValue(int fieldID) {
+      switch (fieldID) {
+      case TABLENAME:
+        return getTablename();
+
+      case KEY:
+        return getKey();
+
+      case COLUMNFAMILY:
+        return getColumnFamily();
+
+      case COLUMNNAMES:
+        return getColumnNames();
+
+      default:
+        throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
+      }
+    }
+
+    // Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise
+    public boolean isSet(int fieldID) {
+      switch (fieldID) {
+      case TABLENAME:
+        return isSetTablename();
+      case KEY:
+        return isSetKey();
+      case COLUMNFAMILY:
+        return isSetColumnFamily();
+      case COLUMNNAMES:
+        return isSetColumnNames();
+      default:
+        throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
+      }
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof get_slice_by_names_args)
+        return this.equals((get_slice_by_names_args)that);
+      return false;
+    }
+
+    public boolean equals(get_slice_by_names_args that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_tablename = true && this.isSetTablename();
+      boolean that_present_tablename = true && that.isSetTablename();
+      if (this_present_tablename || that_present_tablename) {
+        if (!(this_present_tablename && that_present_tablename))
+          return false;
+        if (!this.tablename.equals(that.tablename))
+          return false;
+      }
+
+      boolean this_present_key = true && this.isSetKey();
+      boolean that_present_key = true && that.isSetKey();
+      if (this_present_key || that_present_key) {
+        if (!(this_present_key && that_present_key))
+          return false;
+        if (!this.key.equals(that.key))
+          return false;
+      }
+
+      boolean this_present_columnFamily = true && this.isSetColumnFamily();
+      boolean that_present_columnFamily = true && that.isSetColumnFamily();
+      if (this_present_columnFamily || that_present_columnFamily) {
+        if (!(this_present_columnFamily && that_present_columnFamily))
+          return false;
+        if (!this.columnFamily.equals(that.columnFamily))
+          return false;
+      }
+
+      boolean this_present_columnNames = true && this.isSetColumnNames();
+      boolean that_present_columnNames = true && that.isSetColumnNames();
+      if (this_present_columnNames || that_present_columnNames) {
+        if (!(this_present_columnNames && that_present_columnNames))
+          return false;
+        if (!this.columnNames.equals(that.columnNames))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public void read(TProtocol iprot) throws TException {
+      TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == TType.STOP) { 
+          break;
+        }
+        switch (field.id)
+        {
+          case TABLENAME:
+            if (field.type == TType.STRING) {
+              this.tablename = iprot.readString();
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          case KEY:
+            if (field.type == TType.STRING) {
+              this.key = iprot.readString();
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          case COLUMNFAMILY:
+            if (field.type == TType.STRING) {
+              this.columnFamily = iprot.readString();
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          case COLUMNNAMES:
+            if (field.type == TType.LIST) {
+              {
+                TList _list39 = iprot.readListBegin();
+                this.columnNames = new ArrayList<String>(_list39.size);
+                for (int _i40 = 0; _i40 < _list39.size; ++_i40)
+                {
+                  String _elem41;
+                  _elem41 = iprot.readString();
+                  this.columnNames.add(_elem41);
+                }
+                iprot.readListEnd();
+              }
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            TProtocolUtil.skip(iprot, field.type);
+            break;
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(TProtocol oprot) throws TException {
+      validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (this.tablename != null) {
+        oprot.writeFieldBegin(TABLENAME_FIELD_DESC);
+        oprot.writeString(this.tablename);
+        oprot.writeFieldEnd();
+      }
+      if (this.key != null) {
+        oprot.writeFieldBegin(KEY_FIELD_DESC);
+        oprot.writeString(this.key);
+        oprot.writeFieldEnd();
+      }
+      if (this.columnFamily != null) {
+        oprot.writeFieldBegin(COLUMN_FAMILY_FIELD_DESC);
+        oprot.writeString(this.columnFamily);
+        oprot.writeFieldEnd();
+      }
+      if (this.columnNames != null) {
+        oprot.writeFieldBegin(COLUMN_NAMES_FIELD_DESC);
+        {
+          oprot.writeListBegin(new TList(TType.STRING, this.columnNames.size()));
+          for (String _iter42 : this.columnNames)          {
+            oprot.writeString(_iter42);
+          }
+          oprot.writeListEnd();
+        }
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("get_slice_by_names_args(");
+      boolean first = true;
+
+      sb.append("tablename:");
+      if (this.tablename == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.tablename);
+      }
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("key:");
+      if (this.key == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.key);
+      }
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("columnFamily:");
+      if (this.columnFamily == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.columnFamily);
+      }
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("columnNames:");
+      if (this.columnNames == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.columnNames);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws TException {
+      // check for required fields
+      // check that fields of type enum have valid values
+    }
+
+  }
+
+  public static class get_slice_by_names_result implements TBase, java.io.Serializable, Cloneable   {
+    private static final TStruct STRUCT_DESC = new TStruct("get_slice_by_names_result");
+    private static final TField SUCCESS_FIELD_DESC = new TField("success", TType.LIST, (short)0);
+    private static final TField IRE_FIELD_DESC = new TField("ire", TType.STRUCT, (short)1);
+    private static final TField NFE_FIELD_DESC = new TField("nfe", TType.STRUCT, (short)2);
+
+    public List<column_t> success;
+    public static final int SUCCESS = 0;
+    public InvalidRequestException ire;
+    public static final int IRE = 1;
+    public NotFoundException nfe;
+    public static final int NFE = 2;
+
+    private final Isset __isset = new Isset();
+    private static final class Isset implements java.io.Serializable {
+    }
+
+    public static final Map<Integer, FieldMetaData> metaDataMap = Collections.unmodifiableMap(new HashMap<Integer, FieldMetaData>() {{
+      put(SUCCESS, new FieldMetaData("success", TFieldRequirementType.DEFAULT, 
+          new ListMetaData(TType.LIST, 
+              new StructMetaData(TType.STRUCT, column_t.class))));
+      put(IRE, new FieldMetaData("ire", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.STRUCT)));
+      put(NFE, new FieldMetaData("nfe", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.STRUCT)));
+    }});
+
+    static {
+      FieldMetaData.addStructMetaDataMap(get_slice_by_names_result.class, metaDataMap);
+    }
+
+    public get_slice_by_names_result() {
+    }
+
+    public get_slice_by_names_result(
+      List<column_t> success,
+      InvalidRequestException ire,
+      NotFoundException nfe)
+    {
+      this();
+      this.success = success;
+      this.ire = ire;
+      this.nfe = nfe;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public get_slice_by_names_result(get_slice_by_names_result other) {
+      if (other.isSetSuccess()) {
+        List<column_t> __this__success = new ArrayList<column_t>();
+        for (column_t other_element : other.success) {
+          __this__success.add(new column_t(other_element));
+        }
+        this.success = __this__success;
+      }
+      if (other.isSetIre()) {
+        this.ire = new InvalidRequestException(other.ire);
+      }
+      if (other.isSetNfe()) {
+        this.nfe = new NotFoundException(other.nfe);
+      }
+    }
+
+    @Override
+    public get_slice_by_names_result clone() {
+      return new get_slice_by_names_result(this);
+    }
+
+    public int getSuccessSize() {
+      return (this.success == null) ? 0 : this.success.size();
+    }
+
+    public java.util.Iterator<column_t> getSuccessIterator() {
+      return (this.success == null) ? null : this.success.iterator();
+    }
+
+    public void addToSuccess(column_t elem) {
+      if (this.success == null) {
+        this.success = new ArrayList<column_t>();
+      }
+      this.success.add(elem);
+    }
+
+    public List<column_t> getSuccess() {
+      return this.success;
+    }
+
+    public void setSuccess(List<column_t> success) {
+      this.success = success;
+    }
+
+    public void unsetSuccess() {
+      this.success = null;
+    }
+
+    // Returns true if field success is set (has been asigned a value) and false otherwise
+    public boolean isSetSuccess() {
+      return this.success != null;
+    }
+
+    public void setSuccessIsSet(boolean value) {
+      if (!value) {
+        this.success = null;
+      }
+    }
+
+    public InvalidRequestException getIre() {
+      return this.ire;
+    }
+
+    public void setIre(InvalidRequestException ire) {
+      this.ire = ire;
+    }
+
+    public void unsetIre() {
+      this.ire = null;
+    }
+
+    // Returns true if field ire is set (has been asigned a value) and false otherwise
+    public boolean isSetIre() {
+      return this.ire != null;
+    }
+
+    public void setIreIsSet(boolean value) {
+      if (!value) {
+        this.ire = null;
+      }
+    }
+
+    public NotFoundException getNfe() {
+      return this.nfe;
+    }
+
+    public void setNfe(NotFoundException nfe) {
+      this.nfe = nfe;
+    }
+
+    public void unsetNfe() {
+      this.nfe = null;
+    }
+
+    // Returns true if field nfe is set (has been asigned a value) and false otherwise
+    public boolean isSetNfe() {
+      return this.nfe != null;
+    }
+
+    public void setNfeIsSet(boolean value) {
+      if (!value) {
+        this.nfe = null;
+      }
+    }
+
+    public void setFieldValue(int fieldID, Object value) {
+      switch (fieldID) {
+      case SUCCESS:
+        if (value == null) {
+          unsetSuccess();
+        } else {
+          setSuccess((List<column_t>)value);
+        }
+        break;
+
+      case IRE:
+        if (value == null) {
+          unsetIre();
+        } else {
+          setIre((InvalidRequestException)value);
+        }
+        break;
+
+      case NFE:
+        if (value == null) {
+          unsetNfe();
+        } else {
+          setNfe((NotFoundException)value);
+        }
+        break;
+
+      default:
+        throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
+      }
+    }
+
+    public Object getFieldValue(int fieldID) {
+      switch (fieldID) {
+      case SUCCESS:
+        return getSuccess();
+
+      case IRE:
+        return getIre();
+
+      case NFE:
+        return getNfe();
+
+      default:
+        throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
+      }
+    }
+
+    // Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise
+    public boolean isSet(int fieldID) {
+      switch (fieldID) {
+      case SUCCESS:
+        return isSetSuccess();
+      case IRE:
+        return isSetIre();
+      case NFE:
+        return isSetNfe();
+      default:
+        throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
+      }
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof get_slice_by_names_result)
+        return this.equals((get_slice_by_names_result)that);
+      return false;
+    }
+
+    public boolean equals(get_slice_by_names_result that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_success = true && this.isSetSuccess();
+      boolean that_present_success = true && that.isSetSuccess();
+      if (this_present_success || that_present_success) {
+        if (!(this_present_success && that_present_success))
+          return false;
+        if (!this.success.equals(that.success))
+          return false;
+      }
+
+      boolean this_present_ire = true && this.isSetIre();
+      boolean that_present_ire = true && that.isSetIre();
+      if (this_present_ire || that_present_ire) {
+        if (!(this_present_ire && that_present_ire))
+          return false;
+        if (!this.ire.equals(that.ire))
+          return false;
+      }
+
+      boolean this_present_nfe = true && this.isSetNfe();
+      boolean that_present_nfe = true && that.isSetNfe();
+      if (this_present_nfe || that_present_nfe) {
+        if (!(this_present_nfe && that_present_nfe))
+          return false;
+        if (!this.nfe.equals(that.nfe))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public void read(TProtocol iprot) throws TException {
+      TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == TType.STOP) { 
+          break;
+        }
+        switch (field.id)
+        {
+          case SUCCESS:
+            if (field.type == TType.LIST) {
+              {
+                TList _list43 = iprot.readListBegin();
+                this.success = new ArrayList<column_t>(_list43.size);
+                for (int _i44 = 0; _i44 < _list43.size; ++_i44)
+                {
+                  column_t _elem45;
+                  _elem45 = new column_t();
+                  _elem45.read(iprot);
+                  this.success.add(_elem45);
+                }
+                iprot.readListEnd();
+              }
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          case IRE:
+            if (field.type == TType.STRUCT) {
+              this.ire = new InvalidRequestException();
+              this.ire.read(iprot);
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          case NFE:
+            if (field.type == TType.STRUCT) {
+              this.nfe = new NotFoundException();
+              this.nfe.read(iprot);
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            TProtocolUtil.skip(iprot, field.type);
+            break;
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(TProtocol oprot) throws TException {
+      oprot.writeStructBegin(STRUCT_DESC);
+
+      if (this.isSetSuccess()) {
+        oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+        {
+          oprot.writeListBegin(new TList(TType.STRUCT, this.success.size()));
+          for (column_t _iter46 : this.success)          {
+            _iter46.write(oprot);
+          }
+          oprot.writeListEnd();
+        }
+        oprot.writeFieldEnd();
+      } else if (this.isSetIre()) {
+        oprot.writeFieldBegin(IRE_FIELD_DESC);
+        this.ire.write(oprot);
+        oprot.writeFieldEnd();
+      } else if (this.isSetNfe()) {
+        oprot.writeFieldBegin(NFE_FIELD_DESC);
+        this.nfe.write(oprot);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("get_slice_by_names_result(");
+      boolean first = true;
+
+      sb.append("success:");
+      if (this.success == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.success);
+      }
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("ire:");
+      if (this.ire == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.ire);
+      }
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("nfe:");
+      if (this.nfe == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.nfe);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws TException {
+      // check for required fields
+      // check that fields of type enum have valid values
+    }
+
+  }
+
+  public static class get_slice_from_args implements TBase, java.io.Serializable, Cloneable   {
+    private static final TStruct STRUCT_DESC = new TStruct("get_slice_from_args");
+    private static final TField TABLENAME_FIELD_DESC = new TField("tablename", TType.STRING, (short)1);
+    private static final TField KEY_FIELD_DESC = new TField("key", TType.STRING, (short)2);
+    private static final TField COLUMN_FAMILY_COLUMN_FIELD_DESC = new TField("columnFamily_column", TType.STRING, (short)3);
+    private static final TField IS_ASCENDING_FIELD_DESC = new TField("isAscending", TType.BOOL, (short)4);
+    private static final TField COUNT_FIELD_DESC = new TField("count", TType.I32, (short)5);
+
+    public String tablename;
+    public static final int TABLENAME = 1;
+    public String key;
+    public static final int KEY = 2;
+    public String columnFamily_column;
+    public static final int COLUMNFAMILY_COLUMN = 3;
+    public boolean isAscending;
+    public static final int ISASCENDING = 4;
+    public int count;
+    public static final int COUNT = 5;
+
+    private final Isset __isset = new Isset();
+    private static final class Isset implements java.io.Serializable {
+      public boolean isAscending = false;
+      public boolean count = false;
+    }
+
+    public static final Map<Integer, FieldMetaData> metaDataMap = Collections.unmodifiableMap(new HashMap<Integer, FieldMetaData>() {{
+      put(TABLENAME, new FieldMetaData("tablename", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.STRING)));
+      put(KEY, new FieldMetaData("key", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.STRING)));
+      put(COLUMNFAMILY_COLUMN, new FieldMetaData("columnFamily_column", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.STRING)));
+      put(ISASCENDING, new FieldMetaData("isAscending", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.BOOL)));
+      put(COUNT, new FieldMetaData("count", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.I32)));
+    }});
+
+    static {
+      FieldMetaData.addStructMetaDataMap(get_slice_from_args.class, metaDataMap);
+    }
+
+    public get_slice_from_args() {
+    }
+
+    public get_slice_from_args(
+      String tablename,
+      String key,
+      String columnFamily_column,
+      boolean isAscending,
+      int count)
+    {
+      this();
+      this.tablename = tablename;
+      this.key = key;
+      this.columnFamily_column = columnFamily_column;
+      this.isAscending = isAscending;
+      this.__isset.isAscending = true;
+      this.count = count;
+      this.__isset.count = true;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public get_slice_from_args(get_slice_from_args other) {
+      if (other.isSetTablename()) {
+        this.tablename = other.tablename;
+      }
+      if (other.isSetKey()) {
+        this.key = other.key;
+      }
+      if (other.isSetColumnFamily_column()) {
+        this.columnFamily_column = other.columnFamily_column;
+      }
+      __isset.isAscending = other.__isset.isAscending;
+      this.isAscending = other.isAscending;
+      __isset.count = other.__isset.count;
+      this.count = other.count;
+    }
+
+    @Override
+    public get_slice_from_args clone() {
+      return new get_slice_from_args(this);
+    }
+
+    public String getTablename() {
+      return this.tablename;
+    }
+
+    public void setTablename(String tablename) {
+      this.tablename = tablename;
+    }
+
+    public void unsetTablename() {
+      this.tablename = null;
+    }
+
+    // Returns true if field tablename is set (has been asigned a value) and false otherwise
+    public boolean isSetTablename() {
+      return this.tablename != null;
+    }
+
+    public void setTablenameIsSet(boolean value) {
+      if (!value) {
+        this.tablename = null;
+      }
+    }
+
+    public String getKey() {
+      return this.key;
+    }
+
+    public void setKey(String key) {
+      this.key = key;
+    }
+
+    public void unsetKey() {
+      this.key = null;
+    }
+
+    // Returns true if field key is set (has been asigned a value) and false otherwise
+    public boolean isSetKey() {
+      return this.key != null;
+    }
+
+    public void setKeyIsSet(boolean value) {
+      if (!value) {
+        this.key = null;
+      }
+    }
+
+    public String getColumnFamily_column() {
+      return this.columnFamily_column;
+    }
+
+    public void setColumnFamily_column(String columnFamily_column) {
+      this.columnFamily_column = columnFamily_column;
+    }
+
+    public void unsetColumnFamily_column() {
+      this.columnFamily_column = null;
     }
 
-    // Returns true if field columnFamily is set (has been asigned a value) and false otherwise
-    public boolean isSetColumnFamily() {
-      return this.columnFamily != null;
+    // Returns true if field columnFamily_column is set (has been asigned a value) and false otherwise
+    public boolean isSetColumnFamily_column() {
+      return this.columnFamily_column != null;
     }
 
-    public void setColumnFamilyIsSet(boolean value) {
+    public void setColumnFamily_columnIsSet(boolean value) {
       if (!value) {
-        this.columnFamily = null;
+        this.columnFamily_column = null;
       }
     }
 
-    public int getColumnNamesSize() {
-      return (this.columnNames == null) ? 0 : this.columnNames.size();
+    public boolean isIsAscending() {
+      return this.isAscending;
     }
 
-    public java.util.Iterator<String> getColumnNamesIterator() {
-      return (this.columnNames == null) ? null : this.columnNames.iterator();
+    public void setIsAscending(boolean isAscending) {
+      this.isAscending = isAscending;
+      this.__isset.isAscending = true;
     }
 
-    public void addToColumnNames(String elem) {
-      if (this.columnNames == null) {
-        this.columnNames = new ArrayList<String>();
-      }
-      this.columnNames.add(elem);
+    public void unsetIsAscending() {
+      this.__isset.isAscending = false;
     }
 
-    public List<String> getColumnNames() {
-      return this.columnNames;
+    // Returns true if field isAscending is set (has been asigned a value) and false otherwise
+    public boolean isSetIsAscending() {
+      return this.__isset.isAscending;
     }
 
-    public void setColumnNames(List<String> columnNames) {
-      this.columnNames = columnNames;
+    public void setIsAscendingIsSet(boolean value) {
+      this.__isset.isAscending = value;
     }
 
-    public void unsetColumnNames() {
-      this.columnNames = null;
+    public int getCount() {
+      return this.count;
     }
 
-    // Returns true if field columnNames is set (has been asigned a value) and false otherwise
-    public boolean isSetColumnNames() {
-      return this.columnNames != null;
+    public void setCount(int count) {
+      this.count = count;
+      this.__isset.count = true;
     }
 
-    public void setColumnNamesIsSet(boolean value) {
-      if (!value) {
-        this.columnNames = null;
-      }
+    public void unsetCount() {
+      this.__isset.count = false;
+    }
+
+    // Returns true if field count is set (has been asigned a value) and false otherwise
+    public boolean isSetCount() {
+      return this.__isset.count;
+    }
+
+    public void setCountIsSet(boolean value) {
+      this.__isset.count = value;
     }
 
     public void setFieldValue(int fieldID, Object value) {
@@ -3381,19 +4315,27 @@
         }
         break;
 
-      case COLUMNFAMILY:
+      case COLUMNFAMILY_COLUMN:
         if (value == null) {
-          unsetColumnFamily();
+          unsetColumnFamily_column();
         } else {
-          setColumnFamily((String)value);
+          setColumnFamily_column((String)value);
         }
         break;
 
-      case COLUMNNAMES:
+      case ISASCENDING:
         if (value == null) {
-          unsetColumnNames();
+          unsetIsAscending();
         } else {
-          setColumnNames((List<String>)value);
+          setIsAscending((Boolean)value);
+        }
+        break;
+
+      case COUNT:
+        if (value == null) {
+          unsetCount();
+        } else {
+          setCount((Integer)value);
         }
         break;
 
@@ -3410,11 +4352,14 @@
       case KEY:
         return getKey();
 
-      case COLUMNFAMILY:
-        return getColumnFamily();
+      case COLUMNFAMILY_COLUMN:
+        return getColumnFamily_column();
 
-      case COLUMNNAMES:
-        return getColumnNames();
+      case ISASCENDING:
+        return new Boolean(isIsAscending());
+
+      case COUNT:
+        return new Integer(getCount());
 
       default:
         throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
@@ -3428,10 +4373,12 @@
         return isSetTablename();
       case KEY:
         return isSetKey();
-      case COLUMNFAMILY:
-        return isSetColumnFamily();
-      case COLUMNNAMES:
-        return isSetColumnNames();
+      case COLUMNFAMILY_COLUMN:
+        return isSetColumnFamily_column();
+      case ISASCENDING:
+        return isSetIsAscending();
+      case COUNT:
+        return isSetCount();
       default:
         throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!");
       }
@@ -3441,12 +4388,12 @@
     public boolean equals(Object that) {
       if (that == null)
         return false;
-      if (that instanceof get_slice_by_names_args)
-        return this.equals((get_slice_by_names_args)that);
+      if (that instanceof get_slice_from_args)
+        return this.equals((get_slice_from_args)that);
       return false;
     }
 
-    public boolean equals(get_slice_by_names_args that) {
+    public boolean equals(get_slice_from_args that) {
       if (that == null)
         return false;
 
@@ -3468,21 +4415,30 @@
           return false;
       }
 
-      boolean this_present_columnFamily = true && this.isSetColumnFamily();
-      boolean that_present_columnFamily = true && that.isSetColumnFamily();
-      if (this_present_columnFamily || that_present_columnFamily) {
-        if (!(this_present_columnFamily && that_present_columnFamily))
+      boolean this_present_columnFamily_column = true && this.isSetColumnFamily_column();
+      boolean that_present_columnFamily_column = true && that.isSetColumnFamily_column();
+      if (this_present_columnFamily_column || that_present_columnFamily_column) {
+        if (!(this_present_columnFamily_column && that_present_columnFamily_column))
           return false;
-        if (!this.columnFamily.equals(that.columnFamily))
+        if (!this.columnFamily_column.equals(that.columnFamily_column))
           return false;
       }
 
-      boolean this_present_columnNames = true && this.isSetColumnNames();
-      boolean that_present_columnNames = true && that.isSetColumnNames();
-      if (this_present_columnNames || that_present_columnNames) {
-        if (!(this_present_columnNames && that_present_columnNames))
+      boolean this_present_isAscending = true;
+      boolean that_present_isAscending = true;
+      if (this_present_isAscending || that_present_isAscending) {
+        if (!(this_present_isAscending && that_present_isAscending))
           return false;
-        if (!this.columnNames.equals(that.columnNames))
+        if (this.isAscending != that.isAscending)
+          return false;
+      }
+
+      boolean this_present_count = true;
+      boolean that_present_count = true;
+      if (this_present_count || that_present_count) {
+        if (!(this_present_count && that_present_count))
+          return false;
+        if (this.count != that.count)
           return false;
       }
 
@@ -3519,26 +4475,25 @@
               TProtocolUtil.skip(iprot, field.type);
             }
             break;
-          case COLUMNFAMILY:
+          case COLUMNFAMILY_COLUMN:
             if (field.type == TType.STRING) {
-              this.columnFamily = iprot.readString();
+              this.columnFamily_column = iprot.readString();
             } else { 
               TProtocolUtil.skip(iprot, field.type);
             }
             break;
-          case COLUMNNAMES:
-            if (field.type == TType.LIST) {
-              {
-                TList _list39 = iprot.readListBegin();
-                this.columnNames = new ArrayList<String>(_list39.size);
-                for (int _i40 = 0; _i40 < _list39.size; ++_i40)
-                {
-                  String _elem41;
-                  _elem41 = iprot.readString();
-                  this.columnNames.add(_elem41);
-                }
-                iprot.readListEnd();
-              }
+          case ISASCENDING:
+            if (field.type == TType.BOOL) {
+              this.isAscending = iprot.readBool();
+              this.__isset.isAscending = true;
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          case COUNT:
+            if (field.type == TType.I32) {
+              this.count = iprot.readI32();
+              this.__isset.count = true;
             } else { 
               TProtocolUtil.skip(iprot, field.type);
             }
@@ -3570,29 +4525,24 @@
         oprot.writeString(this.key);
         oprot.writeFieldEnd();
       }
-      if (this.columnFamily != null) {
-        oprot.writeFieldBegin(COLUMN_FAMILY_FIELD_DESC);
-        oprot.writeString(this.columnFamily);
-        oprot.writeFieldEnd();
-      }
-      if (this.columnNames != null) {
-        oprot.writeFieldBegin(COLUMN_NAMES_FIELD_DESC);
-        {
-          oprot.writeListBegin(new TList(TType.STRING, this.columnNames.size()));
-          for (String _iter42 : this.columnNames)          {
-            oprot.writeString(_iter42);
-          }
-          oprot.writeListEnd();
-        }
+      if (this.columnFamily_column != null) {
+        oprot.writeFieldBegin(COLUMN_FAMILY_COLUMN_FIELD_DESC);
+        oprot.writeString(this.columnFamily_column);
         oprot.writeFieldEnd();
       }
+      oprot.writeFieldBegin(IS_ASCENDING_FIELD_DESC);
+      oprot.writeBool(this.isAscending);
+      oprot.writeFieldEnd();
+      oprot.writeFieldBegin(COUNT_FIELD_DESC);
+      oprot.writeI32(this.count);
+      oprot.writeFieldEnd();
       oprot.writeFieldStop();
       oprot.writeStructEnd();
     }
 
     @Override
     public String toString() {
-      StringBuilder sb = new StringBuilder("get_slice_by_names_args(");
+      StringBuilder sb = new StringBuilder("get_slice_from_args(");
       boolean first = true;
 
       sb.append("tablename:");
@@ -3611,20 +4561,20 @@
       }
       first = false;
       if (!first) sb.append(", ");
-      sb.append("columnFamily:");
-      if (this.columnFamily == null) {
+      sb.append("columnFamily_column:");
+      if (this.columnFamily_column == null) {
         sb.append("null");
       } else {
-        sb.append(this.columnFamily);
+        sb.append(this.columnFamily_column);
       }
       first = false;
       if (!first) sb.append(", ");
-      sb.append("columnNames:");
-      if (this.columnNames == null) {
-        sb.append("null");
-      } else {
-        sb.append(this.columnNames);
-      }
+      sb.append("isAscending:");
+      sb.append(this.isAscending);
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("count:");
+      sb.append(this.count);
       first = false;
       sb.append(")");
       return sb.toString();
@@ -3637,8 +4587,8 @@
 
   }
 
-  public static class get_slice_by_names_result implements TBase, java.io.Serializable, Cloneable   {
-    private static final TStruct STRUCT_DESC = new TStruct("get_slice_by_names_result");
+  public static class get_slice_from_result implements TBase, java.io.Serializable, Cloneable   {
+    private static final TStruct STRUCT_DESC = new TStruct("get_slice_from_result");
     private static final TField SUCCESS_FIELD_DESC = new TField("success", TType.LIST, (short)0);
     private static final TField IRE_FIELD_DESC = new TField("ire", TType.STRUCT, (short)1);
     private static final TField NFE_FIELD_DESC = new TField("nfe", TType.STRUCT, (short)2);
@@ -3665,13 +4615,13 @@
     }});
 
     static {
-      FieldMetaData.addStructMetaDataMap(get_slice_by_names_result.class, metaDataMap);
+      FieldMetaData.addStructMetaDataMap(get_slice_from_result.class, metaDataMap);
     }
 
-    public get_slice_by_names_result() {
+    public get_slice_from_result() {
     }
 
-    public get_slice_by_names_result(
+    public get_slice_from_result(
       List<column_t> success,
       InvalidRequestException ire,
       NotFoundException nfe)
@@ -3685,7 +4635,7 @@
     /**
      * Performs a deep copy on <i>other</i>.
      */
-    public get_slice_by_names_result(get_slice_by_names_result other) {
+    public get_slice_from_result(get_slice_from_result other) {
       if (other.isSetSuccess()) {
         List<column_t> __this__success = new ArrayList<column_t>();
         for (column_t other_element : other.success) {
@@ -3702,8 +4652,8 @@
     }
 
     @Override
-    public get_slice_by_names_result clone() {
-      return new get_slice_by_names_result(this);
+    public get_slice_from_result clone() {
+      return new get_slice_from_result(this);
     }
 
     public int getSuccessSize() {
@@ -3855,12 +4805,12 @@
     public boolean equals(Object that) {
       if (that == null)
         return false;
-      if (that instanceof get_slice_by_names_result)
-        return this.equals((get_slice_by_names_result)that);
+      if (that instanceof get_slice_from_result)
+        return this.equals((get_slice_from_result)that);
       return false;
     }
 
-    public boolean equals(get_slice_by_names_result that) {
+    public boolean equals(get_slice_from_result that) {
       if (that == null)
         return false;
 
@@ -3913,14 +4863,14 @@
           case SUCCESS:
             if (field.type == TType.LIST) {
               {
-                TList _list43 = iprot.readListBegin();
-                this.success = new ArrayList<column_t>(_list43.size);
-                for (int _i44 = 0; _i44 < _list43.size; ++_i44)
+                TList _list47 = iprot.readListBegin();
+                this.success = new ArrayList<column_t>(_list47.size);
+                for (int _i48 = 0; _i48 < _list47.size; ++_i48)
                 {
-                  column_t _elem45;
-                  _elem45 = new column_t();
-                  _elem45.read(iprot);
-                  this.success.add(_elem45);
+                  column_t _elem49;
+                  _elem49 = new column_t();
+                  _elem49.read(iprot);
+                  this.success.add(_elem49);
                 }
                 iprot.readListEnd();
               }
@@ -3964,8 +4914,8 @@
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new TList(TType.STRUCT, this.success.size()));
-          for (column_t _iter46 : this.success)          {
-            _iter46.write(oprot);
+          for (column_t _iter50 : this.success)          {
+            _iter50.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -3985,7 +4935,7 @@
 
     @Override
     public String toString() {
-      StringBuilder sb = new StringBuilder("get_slice_by_names_result(");
+      StringBuilder sb = new StringBuilder("get_slice_from_result(");
       boolean first = true;
 
       sb.append("success:");
@@ -8191,14 +9141,14 @@
           case SUCCESS:
             if (field.type == TType.LIST) {
               {
-                TList _list47 = iprot.readListBegin();
-                this.success = new ArrayList<column_t>(_list47.size);
-                for (int _i48 = 0; _i48 < _list47.size; ++_i48)
+                TList _list51 = iprot.readListBegin();
+                this.success = new ArrayList<column_t>(_list51.size);
+                for (int _i52 = 0; _i52 < _list51.size; ++_i52)
                 {
-                  column_t _elem49;
-                  _elem49 = new column_t();
-                  _elem49.read(iprot);
-                  this.success.add(_elem49);
+                  column_t _elem53;
+                  _elem53 = new column_t();
+                  _elem53.read(iprot);
+                  this.success.add(_elem53);
                 }
                 iprot.readListEnd();
               }
@@ -8242,8 +9192,8 @@
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new TList(TType.STRUCT, this.success.size()));
-          for (column_t _iter50 : this.success)          {
-            _iter50.write(oprot);
+          for (column_t _iter54 : this.success)          {
+            _iter54.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -9014,14 +9964,14 @@
           case SUCCESS:
             if (field.type == TType.LIST) {
               {
-                TList _list51 = iprot.readListBegin();
-                this.success = new ArrayList<superColumn_t>(_list51.size);
-                for (int _i52 = 0; _i52 < _list51.size; ++_i52)
+                TList _list55 = iprot.readListBegin();
+                this.success = new ArrayList<superColumn_t>(_list55.size);
+                for (int _i56 = 0; _i56 < _list55.size; ++_i56)
                 {
-                  superColumn_t _elem53;
-                  _elem53 = new superColumn_t();
-                  _elem53.read(iprot);
-                  this.success.add(_elem53);
+                  superColumn_t _elem57;
+                  _elem57 = new superColumn_t();
+                  _elem57.read(iprot);
+                  this.success.add(_elem57);
                 }
                 iprot.readListEnd();
               }
@@ -9057,8 +10007,8 @@
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new TList(TType.STRUCT, this.success.size()));
-          for (superColumn_t _iter54 : this.success)          {
-            _iter54.write(oprot);
+          for (superColumn_t _iter58 : this.success)          {
+            _iter58.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -9455,13 +10405,13 @@
           case SUPERCOLUMNNAMES:
             if (field.type == TType.LIST) {
               {
-                TList _list55 = iprot.readListBegin();
-                this.superColumnNames = new ArrayList<String>(_list55.size);
-                for (int _i56 = 0; _i56 < _list55.size; ++_i56)
+                TList _list59 = iprot.readListBegin();
+                this.superColumnNames = new ArrayList<String>(_list59.size);
+                for (int _i60 = 0; _i60 < _list59.size; ++_i60)
                 {
-                  String _elem57;
-                  _elem57 = iprot.readString();
-                  this.superColumnNames.add(_elem57);
+                  String _elem61;
+                  _elem61 = iprot.readString();
+                  this.superColumnNames.add(_elem61);
                 }
                 iprot.readListEnd();
               }
@@ -9505,8 +10455,8 @@
         oprot.writeFieldBegin(SUPER_COLUMN_NAMES_FIELD_DESC);
         {
           oprot.writeListBegin(new TList(TType.STRING, this.superColumnNames.size()));
-          for (String _iter58 : this.superColumnNames)          {
-            oprot.writeString(_iter58);
+          for (String _iter62 : this.superColumnNames)          {
+            oprot.writeString(_iter62);
           }
           oprot.writeListEnd();
         }
@@ -9784,14 +10734,14 @@
           case SUCCESS:
             if (field.type == TType.LIST) {
               {
-                TList _list59 = iprot.readListBegin();
-                this.success = new ArrayList<superColumn_t>(_list59.size);
-                for (int _i60 = 0; _i60 < _list59.size; ++_i60)
+                TList _list63 = iprot.readListBegin();
+                this.success = new ArrayList<superColumn_t>(_list63.size);
+                for (int _i64 = 0; _i64 < _list63.size; ++_i64)
                 {
-                  superColumn_t _elem61;
-                  _elem61 = new superColumn_t();
-                  _elem61.read(iprot);
-                  this.success.add(_elem61);
+                  superColumn_t _elem65;
+                  _elem65 = new superColumn_t();
+                  _elem65.read(iprot);
+                  this.success.add(_elem65);
                 }
                 iprot.readListEnd();
               }
@@ -9827,8 +10777,8 @@
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new TList(TType.STRUCT, this.success.size()));
-          for (superColumn_t _iter62 : this.success)          {
-            _iter62.write(oprot);
+          for (superColumn_t _iter66 : this.success)          {
+            _iter66.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -12032,13 +12982,13 @@
           case SUCCESS:
             if (field.type == TType.LIST) {
               {
-                TList _list63 = iprot.readListBegin();
-                this.success = new ArrayList<String>(_list63.size);
-                for (int _i64 = 0; _i64 < _list63.size; ++_i64)
+                TList _list67 = iprot.readListBegin();
+                this.success = new ArrayList<String>(_list67.size);
+                for (int _i68 = 0; _i68 < _list67.size; ++_i68)
                 {
-                  String _elem65;
-                  _elem65 = iprot.readString();
-                  this.success.add(_elem65);
+                  String _elem69;
+                  _elem69 = iprot.readString();
+                  this.success.add(_elem69);
                 }
                 iprot.readListEnd();
               }
@@ -12074,8 +13024,8 @@
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new TList(TType.STRING, this.success.size()));
-          for (String _iter66 : this.success)          {
-            oprot.writeString(_iter66);
+          for (String _iter70 : this.success)          {
+            oprot.writeString(_iter70);
           }
           oprot.writeListEnd();
         }
@@ -12882,13 +13832,13 @@
           case SUCCESS:
             if (field.type == TType.LIST) {
               {
-                TList _list67 = iprot.readListBegin();
-                this.success = new ArrayList<String>(_list67.size);
-                for (int _i68 = 0; _i68 < _list67.size; ++_i68)
+                TList _list71 = iprot.readListBegin();
+                this.success = new ArrayList<String>(_list71.size);
+                for (int _i72 = 0; _i72 < _list71.size; ++_i72)
                 {
-                  String _elem69;
-                  _elem69 = iprot.readString();
-                  this.success.add(_elem69);
+                  String _elem73;
+                  _elem73 = iprot.readString();
+                  this.success.add(_elem73);
                 }
                 iprot.readListEnd();
               }
@@ -12916,8 +13866,8 @@
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new TList(TType.STRING, this.success.size()));
-          for (String _iter70 : this.success)          {
-            oprot.writeString(_iter70);
+          for (String _iter74 : this.success)          {
+            oprot.writeString(_iter74);
           }
           oprot.writeListEnd();
         }

Added: incubator/cassandra/trunk/lib/google-collect-1.0-rc1.jar
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/lib/google-collect-1.0-rc1.jar?rev=777578&view=auto
==============================================================================
Files incubator/cassandra/trunk/lib/google-collect-1.0-rc1.jar (added) and incubator/cassandra/trunk/lib/google-collect-1.0-rc1.jar Fri May 22 15:33:42 2009 differ

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnComparatorFactory.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnComparatorFactory.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnComparatorFactory.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnComparatorFactory.java Fri May 22 15:33:42 2009
@@ -39,37 +39,15 @@
 
     public static Comparator<IColumn> getComparator(ComparatorType comparatorType)
     {
-        Comparator<IColumn> columnComparator = timestampComparator_;
-
-        switch (comparatorType)
-        {
-            case NAME:
-                columnComparator = nameComparator_;
-                break;
-
-            case TIMESTAMP:
-
-            default:
-                columnComparator = timestampComparator_;
-                break;
-        }
-
-        return columnComparator;
+        if (comparatorType == ComparatorType.NAME)
+            return nameComparator_;
+        assert comparatorType == ComparatorType.TIMESTAMP;
+        return timestampComparator_;
     }
 
     public static Comparator<IColumn> getComparator(int comparatorTypeInt)
     {
-        ComparatorType comparatorType = ComparatorType.NAME;
-
-        if (comparatorTypeInt == ComparatorType.NAME.ordinal())
-        {
-            comparatorType = ComparatorType.NAME;
-        }
-        else if (comparatorTypeInt == ComparatorType.TIMESTAMP.ordinal())
-        {
-            comparatorType = ComparatorType.TIMESTAMP;
-        }
-        return getComparator(comparatorType);
+        return getComparator(ComparatorType.values()[comparatorTypeInt]);
     }
 
 }

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java Fri May 22 15:33:42 2009
@@ -247,6 +247,7 @@
     void clear()
     {
     	columns_.clear();
+    	size_.set(0);
     }
 
     /*
@@ -301,21 +302,26 @@
     	columns_.remove(columnName);
     }
 
-    void delete(int localtime, long timestamp)
+    public void delete(int localtime, long timestamp)
     {
         localDeletionTime = localtime;
         markedForDeleteAt = timestamp;
     }
 
+    public void delete(ColumnFamily cf2)
+    {
+        delete(Math.max(getLocalDeletionTime(), cf2.getLocalDeletionTime()),
+               Math.max(getMarkedForDeleteAt(), cf2.getMarkedForDeleteAt()));
+    }
+
     public boolean isMarkedForDelete()
     {
         return markedForDeleteAt > Long.MIN_VALUE;
     }
 
     /*
-     * This function will calculate the differnce between 2 column families
-     * the external input is considered the superset of internal
-     * so there are no deletes in the diff.
+     * This function will calculate the difference between 2 column families.
+     * The external input is assumed to be a superset of internal.
      */
     ColumnFamily diff(ColumnFamily cfComposite)
     {
@@ -446,8 +452,7 @@
         {
             assert cf.name().equals(cf2.name());
             cf.addColumns(cf2);
-            cf.delete(Math.max(cf.getLocalDeletionTime(), cf2.getLocalDeletionTime()),
-                      Math.max(cf.getMarkedForDeleteAt(), cf2.getMarkedForDeleteAt()));
+            cf.delete(cf2);
         }
         return cf;
     }

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Fri May 22 15:33:42 2009
@@ -45,6 +45,10 @@
 import org.apache.cassandra.utils.*;
 import org.apache.cassandra.concurrent.DebuggableThreadPoolExecutor;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.comparators.ReverseComparator;
+
 import org.cliffc.high_scale_lib.NonBlockingHashMap;
 import org.cliffc.high_scale_lib.NonBlockingHashSet;
 
@@ -1567,4 +1571,119 @@
     {
         return readStats_.mean();
     }
+
+    /**
+     * get a list of columns starting from a given column, in a specified order
+     * only the latest version of a column is returned
+     */
+    public ColumnFamily getSliceFrom(String key, String cfName, String startColumn, boolean isAscending, int count)
+    throws IOException, ExecutionException, InterruptedException
+    {
+        lock_.readLock().lock();
+        try
+        {
+            final ColumnFamily returnCF;
+            ColumnIterator iter;
+            List<ColumnIterator> iterators = new ArrayList<ColumnIterator>();
+        
+            /* add the current memtable */
+            memtableLock_.readLock().lock();
+            try
+            {
+                iter = memtable_.getColumnIterator(key, cfName, isAscending, startColumn);
+                returnCF = iter.getColumnFamily();
+            }
+            finally
+            {
+                memtableLock_.readLock().unlock();            
+            }        
+            iterators.add(iter);
+
+            /* add the memtables being flushed */
+            List<Memtable> memtables = getUnflushedMemtables(cfName);
+            for (Memtable memtable:memtables)
+            {
+                iter = memtable.getColumnIterator(key, cfName, isAscending, startColumn);
+                returnCF.delete(iter.getColumnFamily());
+                iterators.add(iter);
+            }
+
+            /* add the SSTables on disk */
+            List<String> files = new ArrayList<String>(ssTables_);
+            for (String file : files)
+            {
+                // If the key is not present in the SSTable's BloomFilter, continue to the next file
+                if (!SSTable.isKeyInFile(key, file))
+                    continue;
+                iter = new SSTableColumnIterator(file, key, cfName, startColumn, isAscending);
+                if (iter.hasNext())
+                {
+                    returnCF.delete(iter.getColumnFamily());
+                    iterators.add(iter);
+                }
+            }
+
+            // define a 'reduced' iterator that merges columns w/ the same name, which
+            // greatly simplifies computing liveColumns in the presence of tombstones.
+            Comparator<IColumn> comparator = new Comparator<IColumn>()
+            {
+                public int compare(IColumn c1, IColumn c2)
+                {
+                    return c1.name().compareTo(c2.name());
+                }
+            };
+            if (!isAscending)
+                comparator = new ReverseComparator(comparator);
+            Iterator collated = IteratorUtils.collatedIterator(comparator, iterators);
+            if (!collated.hasNext())
+                return new ColumnFamily(cfName, DatabaseDescriptor.getColumnFamilyType(cfName));
+            List<IColumn> L = new ArrayList();
+            CollectionUtils.addAll(L, collated);
+            ReducingIterator<IColumn> reduced = new ReducingIterator<IColumn>(L.iterator())
+            {
+                ColumnFamily curCF = returnCF.cloneMeShallow();
+
+                protected Object getKey(IColumn o)
+                {
+                    return o == null ? null : o.name();
+                }
+
+                public void reduce(IColumn current)
+                {
+                    curCF.addColumn(current);
+                }
+
+                protected IColumn getReduced()
+                {
+                    IColumn c = curCF.getAllColumns().first();
+                    curCF.clear();
+                    return c;
+                }
+            };
+
+            // add unique columns to the CF container
+            int liveColumns = 0;
+            for (IColumn column : reduced)
+            {
+                if (liveColumns >= count)
+                {
+                    break;
+                }
+                if (!column.isMarkedForDelete())
+                    liveColumns++;
+
+                returnCF.addColumn(column);
+            }
+
+            /* close remaining cursors */
+            for (ColumnIterator ci : iterators)
+                ci.close();
+
+            return removeDeleted(returnCF);
+        }
+        finally
+        {
+            lock_.readLock().unlock();
+        }
+    }
 }

Added: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java?rev=777578&view=auto
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java (added)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java Fri May 22 15:33:42 2009
@@ -0,0 +1,134 @@
+/**
+ * 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.cassandra.db;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.cassandra.io.DataInputBuffer;
+import org.apache.cassandra.io.DataOutputBuffer;
+import org.apache.cassandra.io.SSTable;
+import org.apache.cassandra.io.SequenceFile.ColumnGroupReader;
+import org.apache.cassandra.service.StorageService;
+import com.google.common.collect.AbstractIterator;
+
+public interface ColumnIterator extends Iterator<IColumn>
+{
+    /**
+     *  returns the CF of the column being iterated.
+     *  The CF is only guaranteed to be available after a call to next() or hasNext().
+     */
+    public abstract ColumnFamily getColumnFamily();
+
+    /** clean up any open resources */
+    public void close() throws IOException;
+}
+
+/**
+ *  A Column Iterator over SSTable
+ */
+class SSTableColumnIterator extends AbstractIterator<IColumn> implements ColumnIterator
+{
+    protected boolean isAscending;
+    private String startColumn;
+    private DataOutputBuffer outBuf = new DataOutputBuffer();
+    private DataInputBuffer inBuf = new DataInputBuffer();
+    private int curColumnIndex;
+    private ColumnFamily curCF = null;
+    private ArrayList<IColumn> curColumns = new ArrayList<IColumn>();
+    private ColumnGroupReader reader;
+
+    public SSTableColumnIterator(String filename, String key, String cfName, String startColumn, boolean isAscending)
+    throws IOException
+    {
+        this.isAscending = isAscending;
+        SSTable ssTable = new SSTable(filename, StorageService.getPartitioner());
+        reader = ssTable.getColumnGroupReader(key, cfName, startColumn, isAscending);
+        this.startColumn = startColumn;
+        curColumnIndex = isAscending ? 0 : -1;
+    }
+
+    private boolean isColumnNeeded(IColumn column)
+    {
+        if (isAscending)
+            return (column.name().compareTo(startColumn) >= 0);
+        else
+            return (column.name().compareTo(startColumn) <= 0);
+    }
+
+    private void getColumnsFromBuffer() throws IOException
+    {
+        inBuf.reset(outBuf.getData(), outBuf.getLength());
+        ColumnFamily columnFamily = ColumnFamily.serializer().deserialize(inBuf);
+
+        if (curCF == null)
+            curCF = columnFamily.cloneMeShallow();
+        curColumns.clear();
+        for (IColumn column : columnFamily.getAllColumns())
+            if (isColumnNeeded(column))
+                curColumns.add(column);
+
+        if (isAscending)
+            curColumnIndex = 0;
+        else
+            curColumnIndex = curColumns.size() - 1;
+    }
+
+    public ColumnFamily getColumnFamily()
+    {
+        return curCF;
+    }
+
+    protected IColumn computeNext()
+    {
+        while (true)
+        {
+            if (isAscending)
+            {
+                if (curColumnIndex < curColumns.size())
+                {
+                    return curColumns.get(curColumnIndex++);
+                }
+            }
+            else
+            {
+                if (curColumnIndex >= 0)
+                {
+                    return curColumns.get(curColumnIndex--);
+                }
+            }
+
+            try
+            {
+                if (!reader.getNextBlock(outBuf))
+                    return endOfData();
+                getColumnsFromBuffer();
+            }
+            catch (IOException e)
+            {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public void close() throws IOException
+    {
+        reader.close();
+    }
+}

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/FileStruct.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/FileStruct.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/FileStruct.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/FileStruct.java Fri May 22 15:33:42 2009
@@ -28,6 +28,7 @@
 import org.apache.cassandra.io.Coordinate;
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.log4j.Logger;
+import com.google.common.collect.AbstractIterator;
 
 
 public class FileStruct implements Comparable<FileStruct>, Iterator<String>
@@ -171,10 +172,8 @@
         throw new UnsupportedOperationException();
     }
 
-    private class FileStructIterator
+    private class FileStructIterator extends AbstractIterator<String>
     {
-        String saved;
-
         public FileStructIterator()
         {
             if (key == null)
@@ -184,14 +183,6 @@
                     forward();
                 }
             }
-            if (key.equals(SSTable.blockIndexKey_))
-            {
-                saved = null;
-            }
-            else
-            {
-                saved = key;
-            }
         }
 
         private void forward()
@@ -204,23 +195,17 @@
             {
                 throw new RuntimeException(e);
             }
-            saved = isExhausted() ? null : key;
         }
 
-        public boolean hasNext()
+        protected String computeNext()
         {
-            return saved != null;
-        }
-
-        public String next()
-        {
-            if (saved == null)
+            if (key.equals(SSTable.blockIndexKey_))
             {
-                throw new IndexOutOfBoundsException();
+                return endOfData();
             }
-            String key = saved;
+            String oldKey = key;
             forward();
-            return key;
+            return oldKey;
         }
     }
 }

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java Fri May 22 15:33:42 2009
@@ -18,6 +18,14 @@
 
 package org.apache.cassandra.db;
 
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.commons.collections.comparators.ReverseComparator;
+import org.apache.commons.lang.ArrayUtils;
+
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.io.DataOutputBuffer;
@@ -27,13 +35,6 @@
 import org.apache.cassandra.utils.DestructivePQIterator;
 import org.apache.log4j.Logger;
 
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.commons.collections.MapUtils;
-
 /**
  * Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com )
  */
@@ -177,8 +178,7 @@
             int newObjectCount = oldCf.getColumnCount();
             resolveSize(oldSize, newSize);
             resolveCount(oldObjectCount, newObjectCount);
-            oldCf.delete(Math.max(oldCf.getLocalDeletionTime(), columnFamily.getLocalDeletionTime()),
-                         Math.max(oldCf.getMarkedForDeleteAt(), columnFamily.getMarkedForDeleteAt()));
+            oldCf.delete(columnFamily);
         }
         else
         {
@@ -330,4 +330,70 @@
         // race conditions even though a task has been processed.
         return !isDirty_;
     }
+
+    /**
+     * obtain an iterator of columns in this memtable in the specified order starting from a given column.
+     */
+    ColumnIterator getColumnIterator(final String key, final String cfName, final boolean isAscending, String startColumn)
+    {
+        ColumnFamily cf = columnFamilies_.get(key);
+        final ColumnFamily columnFamily;
+        if (cf != null)
+            columnFamily = cf.cloneMeShallow();
+        else
+            columnFamily = new ColumnFamily(cfName, DatabaseDescriptor.getColumnFamilyType(cfName));
+
+        final IColumn columns[] = (cf == null ? columnFamily : cf).getAllColumns().toArray(new IColumn[columnFamily.getAllColumns().size()]);
+        // TODO if we are dealing with supercolumns, we need to clone them while we have the read lock since they can be modified later
+        if (!isAscending)
+            ArrayUtils.reverse(columns);
+        IColumn startIColumn;
+        if (DatabaseDescriptor.getColumnFamilyType(cfName).equals("Standard"))
+            startIColumn = new Column(startColumn);
+        else
+            startIColumn = new SuperColumn(startColumn);
+
+        // can't use a ColumnComparatorFactory comparator since those compare on both name and time (and thus will fail to match
+        // our dummy column, since the time there is arbitrary).
+        Comparator<IColumn> comparator = new Comparator<IColumn>()
+        {
+            public int compare(IColumn column1, IColumn column2)
+            {
+                return column1.name().compareTo(column2.name());
+            }
+        };
+        if (!isAscending)
+        {
+            comparator = new ReverseComparator(comparator);
+        }
+        int index = Arrays.binarySearch(columns, startIColumn, comparator);
+        final int startIndex = index < 0 ? -(index + 1) : index;
+
+        return new ColumnIterator()
+        {
+            private int curIndex_ = startIndex;
+
+            public ColumnFamily getColumnFamily()
+            {
+                return columnFamily;
+            }
+
+            public boolean hasNext()
+            {
+                return curIndex_ < columns.length;
+            }
+
+            public IColumn next()
+            {
+                return columns[curIndex_++];
+            }
+
+            public void close() throws IOException {}
+
+            public void remove()
+            {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
 }

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ReadCommand.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ReadCommand.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ReadCommand.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ReadCommand.java Fri May 22 15:33:42 2009
@@ -39,6 +39,8 @@
     public static final byte CMD_TYPE_GET_COLUMNS_SINCE=4;
     public static final byte CMD_TYPE_GET_SLICE=5;
     public static final byte CMD_TYPE_GET_SLICE_BY_RANGE = 6;
+    public static final byte CMD_TYPE_GET_SLICE_FROM=7;
+
     public static final String EMPTY_CF = "";
     
     private static ReadCommandSerializer serializer = new ReadCommandSerializer();
@@ -96,6 +98,7 @@
         CMD_SERIALIZER_MAP.put(ReadCommand.CMD_TYPE_GET_COLUMNS_SINCE, new ColumnsSinceReadCommandSerializer());
         CMD_SERIALIZER_MAP.put(ReadCommand.CMD_TYPE_GET_SLICE, new SliceReadCommandSerializer());
         CMD_SERIALIZER_MAP.put(ReadCommand.CMD_TYPE_GET_SLICE_BY_RANGE, new SliceByRangeReadCommandSerializer());
+        CMD_SERIALIZER_MAP.put(ReadCommand.CMD_TYPE_GET_SLICE_FROM, new SliceFromReadCommandSerializer());
     }
 
 

Added: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/SliceFromReadCommand.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/SliceFromReadCommand.java?rev=777578&view=auto
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/SliceFromReadCommand.java (added)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/SliceFromReadCommand.java Fri May 22 15:33:42 2009
@@ -0,0 +1,99 @@
+/**
+ * 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.cassandra.db;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class SliceFromReadCommand extends ReadCommand
+{
+    public final String columnFamilyColumn;
+    public final boolean isAscending;
+    public final int count;
+
+    public SliceFromReadCommand(String table, String key, String columnFamilyColumn, boolean isAscending, int count)
+    {
+        super(table, key, CMD_TYPE_GET_SLICE_FROM);
+        this.columnFamilyColumn = columnFamilyColumn;
+        this.isAscending = isAscending;
+        this.count = count;
+    }
+
+    @Override
+    public String getColumnFamilyName()
+    {
+        return RowMutation.getColumnAndColumnFamily(columnFamilyColumn)[0];
+    }
+
+    @Override
+    public ReadCommand copy()
+    {
+        ReadCommand readCommand = new SliceFromReadCommand(table, key, columnFamilyColumn, isAscending, count);
+        readCommand.setDigestQuery(isDigestQuery());
+        return readCommand;
+    }
+
+    @Override
+    public Row getRow(Table table) throws IOException
+    {
+        return table.getSliceFrom(key, columnFamilyColumn, isAscending, count);
+    }
+
+    @Override
+    public String toString()
+    {
+        return "GetSliceReadMessage(" +
+               "table='" + table + '\'' +
+               ", key='" + key + '\'' +
+               ", columnFamily='" + columnFamilyColumn + '\'' +
+               ", isAscending='" + isAscending + '\'' +
+               ", count='" + count + '\'' +
+               ')';
+    }
+}
+
+class SliceFromReadCommandSerializer extends ReadCommandSerializer
+{
+    @Override
+    public void serialize(ReadCommand rm, DataOutputStream dos) throws IOException
+    {
+        SliceFromReadCommand realRM = (SliceFromReadCommand)rm;
+        dos.writeBoolean(realRM.isDigestQuery());
+        dos.writeUTF(realRM.table);
+        dos.writeUTF(realRM.key);
+        dos.writeUTF(realRM.columnFamilyColumn);
+        dos.writeBoolean(realRM.isAscending);
+        dos.writeInt(realRM.count);
+    }
+
+    @Override
+    public ReadCommand deserialize(DataInputStream dis) throws IOException
+    {
+        boolean isDigest = dis.readBoolean();
+        String table = dis.readUTF();
+        String key = dis.readUTF();
+        String columnFamily = dis.readUTF();
+        boolean isAscending = dis.readBoolean();
+        int count = dis.readInt();
+
+        SliceFromReadCommand rm = new SliceFromReadCommand(table, key, columnFamily, isAscending, count);
+        rm.setDigestQuery(isDigest);
+        return rm;
+    }
+}

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=777578&r1=777577&r2=777578&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Fri May 22 15:33:42 2009
@@ -50,10 +50,7 @@
 import org.apache.cassandra.net.io.StreamContextManager;
 import org.apache.cassandra.service.StorageService;
 import org.apache.cassandra.service.CassandraServer;
-import org.apache.cassandra.utils.BasicUtilities;
-import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.utils.FileUtils;
-import org.apache.cassandra.utils.LogUtil;
+import org.apache.cassandra.utils.*;
 import org.apache.log4j.Logger;
 
 /**
@@ -776,6 +773,34 @@
     }
 
     /**
+     * Selects a list of columns in a column family from a given column for the specified key.
+    */
+    public Row getSliceFrom(String key, String cf, boolean isAscending, int count) throws IOException
+    {
+        Row row = new Row(key);
+        String[] values = RowMutation.getColumnAndColumnFamily(cf);
+        ColumnFamilyStore cfStore = columnFamilyStores_.get(values[0]);
+        long start1 = System.currentTimeMillis();
+        try
+        {
+            ColumnFamily columnFamily = cfStore.getSliceFrom(key, values[0], values[1], isAscending, count);
+            if (columnFamily != null)
+                row.addColumnFamily(columnFamily);
+            long timeTaken = System.currentTimeMillis() - start1;
+            dbAnalyticsSource_.updateReadStatistics(timeTaken);
+            return row;
+        }
+        catch (InterruptedException e)
+        {
+            throw new RuntimeException(e);
+        }
+        catch (ExecutionException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
      * This method adds the row to the Commit Log associated with this table.
      * Once this happens the data associated with the individual column families
      * is also written to the column family store's memtable.
@@ -950,39 +975,46 @@
             }
         }
         Iterator<String> collated = IteratorUtils.collatedIterator(comparator, iterators);
+        Iterable<String> reduced = new ReducingIterator<String>(collated) {
+            String current;
+
+            public void reduce(String current)
+            {
+                 this.current = current;
+            }
+
+            protected String getReduced()
+            {
+                return current;
+            }
+        };
 
         try
         {
             // pull keys out of the CollatedIterator.  checking tombstone status is expensive,
             // so we set an arbitrary limit on how many we'll do at once.
             List<String> keys = new ArrayList<String>();
-            String last = null, current = null;
-            while (keys.size() < maxResults)
+            for (String current : reduced)
             {
-                if (!collated.hasNext())
+                if (!stopAt.isEmpty() && comparator.compare(stopAt, current) < 0)
                 {
                     break;
                 }
-                current = collated.next();
-                if (!current.equals(last))
+                // make sure there is actually non-tombstone content associated w/ this key
+                // TODO record the key source(s) somehow and only check that source (e.g., memtable or sstable)
+                for (String cfName : getApplicationColumnFamilies())
                 {
-                    if (!stopAt.isEmpty() && comparator.compare(stopAt, current) < 0)
+                    ColumnFamilyStore cfs = getColumnFamilyStore(cfName);
+                    ColumnFamily cf = cfs.getColumnFamily(current, cfName, new IdentityFilter(), Integer.MAX_VALUE);
+                    if (cf != null && cf.getColumns().size() > 0)
                     {
+                        keys.add(current);
                         break;
                     }
-                    last = current;
-                    // make sure there is actually non-tombstone content associated w/ this key
-                    // TODO record the key source(s) somehow and only check that source (e.g., memtable or sstable)
-                    for (String cfName : getApplicationColumnFamilies())
-                    {
-                        ColumnFamilyStore cfs = getColumnFamilyStore(cfName);
-                        ColumnFamily cf = cfs.getColumnFamily(current, cfName, new IdentityFilter(), Integer.MAX_VALUE);
-                        if (cf != null && cf.getColumns().size() > 0)
-                        {
-                            keys.add(current);
-                            break;
-                        }
-                    }
+                }
+                if (keys.size() >= maxResults)
+                {
+                    break;
                 }
             }
             return keys;