docs: protected Scanner getScanner(final int salt_bucket) throws HBaseException {
      final short metric_width = tsdb.metrics.width();
      
      // set the metric UID based on the TSUIDs if given, or the metric UID
      if (tsuids != null && !tsuids.isEmpty()) {
        final String tsuid = tsuids.get(0);
        final String metric_uid = tsuid.substring(0, metric_width * 2);
        metric = UniqueId.stringToUid(metric_uid);
      }
      
      final boolean is_rollup = RollupQuery.isValidQuery(rollup_query);
      
      // We search at least one row before and one row after the start & end
      // time we've been given as it's quite likely that the exact timestamp
      // we're looking for is in the middle of a row.  Plus, a number of things
      // rely on having a few extra data points before & after the exact start
      // & end dates in order to do proper rate calculation or downsampling near
      // the "edges" of the graph.
      final Scanner scanner = QueryUtil.getMetricScanner(tsdb, salt_bucket, metric, 
          (int) getScanStartTimeSeconds(), end_time == UNSET
          ? -1  // Will scan until the end (0xFFF...).
          : (int) getScanEndTimeSeconds(), 
          tableToBeScanned(), 
          TSDB.FAMILY());
      if(tsdb.getConfig().use_otsdb_timestamp()) {
        long stTime = (getScanStartTimeSeconds() * 1000);
        long endTime = end_time == UNSET ? -1 : (getScanEndTimeSeconds() * 1000);
        if (tsdb.getConfig().get_date_tiered_compaction_start() <= stTime &&
            rollup_query == null) {
          // TODO - we could set this for rollups but we also need to write
          // the rollup columns at the proper time.
          scanner.setTimeRange(stTime, endTime);
        }
      }
      if (tsuids != null && !tsuids.isEmpty()) {
        createAndSetTSUIDFilter(scanner);
      } else if (filters.size() > 0) {
        createAndSetFilter(scanner);
      }
  
      if (is_rollup) {
        ScanFilter existing = scanner.getFilter();
        // TODO - need some UTs around this!
        // Set the Scanners column qualifier pattern with rollup aggregator
        // HBase allows only a single filter so if we have a row key filter, keep
        // it. If not, then we can do this
        if (!rollup_query.getRollupAgg().toString().equals("avg")) {
          if (existing != null) {
            final List<ScanFilter> filters = new ArrayList<ScanFilter>(2);
            filters.add(existing);
            final List<ScanFilter> rollup_filters = new ArrayList<ScanFilter>(2);
            rollup_filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
                new BinaryPrefixComparator(rollup_query.getRollupAgg().toString()
                        .getBytes(Const.ASCII_CHARSET))));
            rollup_filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
                new BinaryPrefixComparator(new byte[] { 
                    (byte) tsdb.getRollupConfig().getIdForAggregator(
                        rollup_query.getRollupAgg().toString())
                })));
            filters.add(new FilterList(rollup_filters, Operator.MUST_PASS_ONE));
            scanner.setFilter(new FilterList(filters, Operator.MUST_PASS_ALL));
          } else {
            final List<ScanFilter> filters = new ArrayList<ScanFilter>(2);
            filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
                new BinaryPrefixComparator(rollup_query.getRollupAgg().toString()
                    .getBytes(Const.ASCII_CHARSET))));
            filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
                new BinaryPrefixComparator(new byte[] { 
                    (byte) tsdb.getRollupConfig().getIdForAggregator(
                        rollup_query.getRollupAgg().toString())
                })));
            scanner.setFilter(new FilterList(filters, Operator.MUST_PASS_ONE));
          }
        } else {
          final List<ScanFilter> filters = new ArrayList<ScanFilter>(4);
          filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
              new BinaryPrefixComparator("sum".getBytes())));
          filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
              new BinaryPrefixComparator("count".getBytes())));
          filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
              new BinaryPrefixComparator(new byte[] {
                  (byte) tsdb.getRollupConfig().getIdForAggregator("sum")
              })));
          filters.add(new QualifierFilter(CompareFilter.CompareOp.EQUAL,
              new BinaryPrefixComparator(new byte[] { 
                  (byte) tsdb.getRollupConfig().getIdForAggregator("count")
              })));
          
          if (existing != null) {
            final List<ScanFilter> combined = new ArrayList<ScanFilter>(2);
            combined.add(existing);
            combined.add(new FilterList(filters, Operator.MUST_PASS_ONE));
            scanner.setFilter(new FilterList(combined, Operator.MUST_PASS_ALL));
          } else {
            scanner.setFilter(new FilterList(filters, Operator.MUST_PASS_ONE));
          }
        }
      }
      return scanner;
    }