public void runQuery() throws IOException {
    MultigetSliceQuery<DataPointsRowKey, Integer, ByteBuffer> msliceQuery =
        HFactory.createMultigetSliceQuery(
            m_keyspace, ROW_KEY_SERIALIZER, IntegerSerializer.get(), ByteBufferSerializer.get());

    msliceQuery.setColumnFamily(m_columnFamily);
    msliceQuery.setKeys(m_rowKeys);
    if (m_descending) msliceQuery.setRange(m_endTime, m_startTime, true, m_multiRowReadSize);
    else msliceQuery.setRange(m_startTime, m_endTime, false, m_multiRowReadSize);

    Rows<DataPointsRowKey, Integer, ByteBuffer> rows = msliceQuery.execute().get();

    List<Row<DataPointsRowKey, Integer, ByteBuffer>> unfinishedRows =
        new ArrayList<Row<DataPointsRowKey, Integer, ByteBuffer>>();

    for (Row<DataPointsRowKey, Integer, ByteBuffer> row : rows) {
      List<HColumn<Integer, ByteBuffer>> columns = row.getColumnSlice().getColumns();
      if (!m_limit && columns.size() == m_multiRowReadSize) unfinishedRows.add(row);

      writeColumns(row.getKey(), columns);
    }

    // Iterate through the unfinished rows and get the rest of the data.
    // todo: use multiple threads to retrieve this data
    for (Row<DataPointsRowKey, Integer, ByteBuffer> unfinishedRow : unfinishedRows) {
      DataPointsRowKey key = unfinishedRow.getKey();

      SliceQuery<DataPointsRowKey, Integer, ByteBuffer> sliceQuery =
          HFactory.createSliceQuery(
              m_keyspace, ROW_KEY_SERIALIZER, IntegerSerializer.get(), ByteBufferSerializer.get());

      sliceQuery.setColumnFamily(m_columnFamily);
      sliceQuery.setKey(key);

      List<HColumn<Integer, ByteBuffer>> columns = unfinishedRow.getColumnSlice().getColumns();

      do {
        Integer lastTime = columns.get(columns.size() - 1).getName();

        if (m_descending) sliceQuery.setRange(lastTime - 1, m_startTime, true, m_singleRowReadSize);
        else sliceQuery.setRange(lastTime + 1, m_endTime, false, m_singleRowReadSize);

        columns = sliceQuery.execute().get().getColumns();
        writeColumns(key, columns);
      } while (columns.size() == m_singleRowReadSize);
    }
  }
  public List<byte[]> scan(
      String startKey, String columnFamilyName, int maxRows) // throws IOException
      {
    List<byte[]> results = new ArrayList<byte[]>();

    MultigetSliceQuery<String, String, byte[]> multigetSliceQuery =
        HFactory.createMultigetSliceQuery(
            this._keyspace,
            StringSerializer.get(),
            StringSerializer.get(),
            BytesArraySerializer.get());
    multigetSliceQuery.setColumnFamily(columnFamilyName);
    multigetSliceQuery.setKeys(startKey);
    multigetSliceQuery.setRange(startKey, "", false, maxRows);
    QueryResult<Rows<String, String, byte[]>> queryResult = multigetSliceQuery.execute();
    Rows<String, String, byte[]> rows = queryResult.get();
    for (Row<String, String, byte[]> row : rows) {
      boolean fail = true;
      HColumn<String, byte[]> column = row.getColumnSlice().getColumnByName(DEFAULT_COLUMN_NAME);
      if (column != null) {
        byte[] value = column.getValue();

        if (value != null) {
          results.add(value);
          fail = false;
          /*
          if (this._debug)
          {
          	String key = rows.getKey();

          	if (this._failMap.containsKey(key))
          	{
          		System.out.println("Successful scan for previously failed key: " + key);
          	}
          }
          */
        }
      }
      if (fail) {
        /*
        if (this._debug)
        {
        	String key = rows.getKey();

        	// Track the keys that fail and check whether we ever see a key for a value that failed before
        	if (this._failMap.containsKey(key))
        	{
        		int count = this._failMap.get(key);
        		count++;
        		this._failMap.put(key, count);
        	}
        	else
        	{
        		this._failMap.put(key, 1);
        	}
        }
        */
      }
    }

    return results;
  }