docs: private List<Row> getKeySlice(Token start,
                                    Token end,
                                    @Nullable SliceQuery sliceQuery,
                                    int pageSize,
                                    long nowMillis) throws BackendException {
          IPartitioner partitioner = StorageService.getPartitioner();
  
          SliceRange columnSlice = new SliceRange();
          if (sliceQuery == null) {
              columnSlice.setStart(ArrayUtils.EMPTY_BYTE_ARRAY)
                      .setFinish(ArrayUtils.EMPTY_BYTE_ARRAY)
                      .setCount(5);
          } else {
              columnSlice.setStart(sliceQuery.getSliceStart().asByteBuffer())
                      .setFinish(sliceQuery.getSliceEnd().asByteBuffer())
                      .setCount(sliceQuery.hasLimit() ? sliceQuery.getLimit() : Integer.MAX_VALUE);
          }
          /* Note: we need to fetch columns for each row as well to remove "range ghosts" */
          SlicePredicate predicate = new SlicePredicate().setSlice_range(columnSlice);
  
          RowPosition startPosition = start.minKeyBound(partitioner);
          RowPosition endPosition = end.minKeyBound(partitioner);
  
          List<Row> rows;
  
          try {
              CFMetaData cfm = Schema.instance.getCFMetaData(keyspace, columnFamily);
              IDiskAtomFilter filter = ThriftValidation.asIFilter(predicate, cfm, null);
  
              RangeSliceCommand cmd = new RangeSliceCommand(keyspace, columnFamily, nowMillis, filter, new Bounds<RowPosition>(startPosition, endPosition), pageSize);
  
              rows = StorageProxy.getRangeSlice(cmd, ConsistencyLevel.QUORUM);
          } catch (Exception e) {
              throw new PermanentBackendException(e);
          }
  
          return rows;
      }