public Column get_column(String table, String key, ColumnPath column_path, int consistency_level)
      throws InvalidRequestException, NotFoundException {
    if (logger.isDebugEnabled()) logger.debug("get_column");
    ThriftValidation.validateColumnPath(table, column_path);

    QueryPath path = new QueryPath(column_path.column_family, column_path.super_column);
    ColumnFamily cfamily =
        readColumnFamily(
            new SliceByNamesReadCommand(table, key, path, Arrays.asList(column_path.column)),
            consistency_level);
    // TODO can we leverage getSlice here and just check that it returns one column?
    if (cfamily == null) {
      throw new NotFoundException();
    }
    Collection<IColumn> columns = null;
    if (column_path.super_column != null) {
      IColumn column = cfamily.getColumn(column_path.super_column);
      if (column != null) {
        columns = column.getSubColumns();
      }
    } else {
      columns = cfamily.getSortedColumns();
    }
    if (columns == null || columns.size() == 0) {
      throw new NotFoundException();
    }

    assert columns.size() == 1;
    IColumn column = columns.iterator().next();
    if (column.isMarkedForDelete()) {
      throw new NotFoundException();
    }

    return new Column(column.name(), column.value(), column.timestamp());
  }
  protected ColumnFamily readColumnFamily(ReadCommand command, int consistency_level)
      throws InvalidRequestException {
    String cfName = command.getColumnFamilyName();
    ThriftValidation.validateKey(command.key);

    if (consistency_level == ConsistencyLevel.ZERO) {
      throw new InvalidRequestException(
          "Consistency level zero may not be applied to read operations");
    }
    if (consistency_level == ConsistencyLevel.ALL) {
      throw new InvalidRequestException(
          "Consistency level all is not yet supported on read operations");
    }

    Row row;
    try {
      row = StorageProxy.readProtocol(command, consistency_level);
    } catch (IOException e) {
      throw new RuntimeException(e);
    } catch (TimeoutException e) {
      throw new RuntimeException(e);
    }

    if (row == null) {
      return null;
    }
    return row.getColumnFamily(cfName);
  }
  public SuperColumn get_super_column(
      String table, String key, SuperColumnPath super_column_path, int consistency_level)
      throws InvalidRequestException, NotFoundException {
    if (logger.isDebugEnabled()) logger.debug("get_superColumn");
    ThriftValidation.validateSuperColumnPath(table, super_column_path);

    ColumnFamily cfamily =
        readColumnFamily(
            new SliceByNamesReadCommand(
                table,
                key,
                new QueryPath(super_column_path.column_family),
                Arrays.asList(super_column_path.super_column)),
            consistency_level);
    if (cfamily == null) {
      throw new NotFoundException();
    }
    Collection<IColumn> columns = cfamily.getSortedColumns();
    if (columns == null || columns.size() == 0) {
      throw new NotFoundException();
    }

    assert columns.size() == 1;
    IColumn column = columns.iterator().next();
    if (column.getSubColumns().size() == 0) {
      throw new NotFoundException();
    }

    return new SuperColumn(column.name(), thriftifyColumns(column.getSubColumns()));
  }
  public void batch_insert(String table, BatchMutation batch_mutation, int consistency_level)
      throws InvalidRequestException, UnavailableException {
    if (logger.isDebugEnabled()) logger.debug("batch_insert");
    RowMutation rm = RowMutation.getRowMutation(table, batch_mutation);
    Set<String> cfNames = rm.columnFamilyNames();
    ThriftValidation.validateKeyCommand(
        rm.key(), rm.table(), cfNames.toArray(new String[cfNames.size()]));

    doInsert(consistency_level, rm);
  }
  public void insert(
      String table,
      String key,
      ColumnPath column_path,
      byte[] value,
      long timestamp,
      int consistency_level)
      throws InvalidRequestException, UnavailableException {
    if (logger.isDebugEnabled()) logger.debug("insert");
    ThriftValidation.validateKey(key);
    ThriftValidation.validateColumnPath(table, column_path);

    RowMutation rm = new RowMutation(table, key.trim());
    try {
      rm.add(new QueryPath(column_path), value, timestamp);
    } catch (MarshalException e) {
      throw new InvalidRequestException(e.getMessage());
    }
    doInsert(consistency_level, rm);
  }
 public List<Column> get_slice_by_names(
     String table,
     String key,
     ColumnParent column_parent,
     List<byte[]> column_names,
     int consistency_level)
     throws InvalidRequestException, NotFoundException {
   if (logger.isDebugEnabled()) logger.debug("get_slice_by_names");
   ThriftValidation.validateColumnParent(table, column_parent);
   return getSlice(
       new SliceByNamesReadCommand(table, key, column_parent, column_names), consistency_level);
 }
  public void remove(
      String table,
      String key,
      ColumnPathOrParent column_path_or_parent,
      long timestamp,
      int consistency_level)
      throws InvalidRequestException, UnavailableException {
    if (logger.isDebugEnabled()) logger.debug("remove");
    ThriftValidation.validateColumnPathOrParent(table, column_path_or_parent);

    RowMutation rm = new RowMutation(table, key.trim());
    rm.delete(new QueryPath(column_path_or_parent), timestamp);

    doInsert(consistency_level, rm);
  }
  public List<Column> get_slice(
      String table,
      String key,
      ColumnParent column_parent,
      byte[] start,
      byte[] finish,
      boolean is_ascending,
      int count,
      int consistency_level)
      throws InvalidRequestException, NotFoundException {
    if (logger.isDebugEnabled()) logger.debug("get_slice_from");
    ThriftValidation.validateColumnParent(table, column_parent);
    // TODO support get_slice on super CFs
    if (count <= 0) throw new InvalidRequestException("get_slice requires positive count");

    return getSlice(
        new SliceFromReadCommand(table, key, column_parent, start, finish, is_ascending, count),
        consistency_level);
  }
  public int get_column_count(
      String table, String key, ColumnParent column_parent, int consistency_level)
      throws InvalidRequestException {
    if (logger.isDebugEnabled()) logger.debug("get_column_count");
    // validateColumnParent assumes we require simple columns; g_c_c is the only
    // one of the columnParent-taking apis that can also work at the SC level.
    // so we roll a one-off validator here.
    String cfType = ThriftValidation.validateColumnFamily(table, column_parent.column_family);
    if (cfType.equals("Standard") && column_parent.super_column != null) {
      throw new InvalidRequestException(
          "columnfamily alone is required for standard CF " + column_parent.column_family);
    }

    ColumnFamily cfamily;
    cfamily =
        readColumnFamily(
            new SliceFromReadCommand(
                table,
                key,
                column_parent,
                ArrayUtils.EMPTY_BYTE_ARRAY,
                ArrayUtils.EMPTY_BYTE_ARRAY,
                true,
                Integer.MAX_VALUE),
            consistency_level);
    if (cfamily == null) {
      return 0;
    }
    Collection<IColumn> columns = null;
    if (column_parent.super_column != null) {
      IColumn column = cfamily.getColumn(column_parent.super_column);
      if (column != null) {
        columns = column.getSubColumns();
      }
    } else {
      columns = cfamily.getSortedColumns();
    }
    if (columns == null || columns.size() == 0) {
      return 0;
    }
    return columns.size();
  }
  public List<String> get_key_range(
      String tablename, String columnFamily, String startWith, String stopAt, int maxResults)
      throws InvalidRequestException, TException {
    if (logger.isDebugEnabled()) logger.debug("get_key_range");
    ThriftValidation.validateCommand(tablename, columnFamily);
    if (!(StorageService.getPartitioner() instanceof OrderPreservingPartitioner)) {
      throw new InvalidRequestException(
          "range queries may only be performed against an order-preserving partitioner");
    }
    if (maxResults <= 0) {
      throw new InvalidRequestException("maxResults must be positive");
    }

    try {
      return StorageProxy.getKeyRange(
          new RangeCommand(tablename, columnFamily, startWith, stopAt, maxResults));
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
  public List<SuperColumn> get_slice_super_by_names(
      String table,
      String key,
      String column_family,
      List<byte[]> super_column_names,
      int consistency_level)
      throws InvalidRequestException {
    if (logger.isDebugEnabled()) logger.debug("get_slice_super_by_names");
    ThriftValidation.validateColumnFamily(table, column_family);

    ColumnFamily cfamily =
        readColumnFamily(
            new SliceByNamesReadCommand(
                table, key, new QueryPath(column_family), super_column_names),
            consistency_level);
    if (cfamily == null) {
      return EMPTY_SUPERCOLUMNS;
    }
    return thriftifySuperColumns(cfamily.getSortedColumns());
  }