@Override
  public LimitedScanResult<List<TransactionId>> scanTraceIndex(
      final String applicationName, SelectedScatterArea area, int limit) {
    if (applicationName == null) {
      throw new NullPointerException("applicationName must not be null");
    }
    if (area == null) {
      throw new NullPointerException("area must not be null");
    }
    if (limit < 0) {
      throw new IllegalArgumentException("negative limit:" + limit);
    }
    logger.debug("scanTraceIndex");
    Scan scan = createScan(applicationName, area.getTimeRange());

    final LimitedScanResult<List<TransactionId>> limitedScanResult = new LimitedScanResult<>();
    LastRowAccessor lastRowAccessor = new LastRowAccessor();
    List<List<TransactionId>> traceIndexList =
        hbaseOperations2.findParallel(
            HBaseTables.APPLICATION_TRACE_INDEX,
            scan,
            traceIdRowKeyDistributor,
            limit,
            traceIndexMapper,
            lastRowAccessor,
            APPLICATION_TRACE_INDEX_NUM_PARTITIONS);

    List<TransactionId> transactionIdSum = new ArrayList<>(128);
    for (List<TransactionId> transactionId : traceIndexList) {
      transactionIdSum.addAll(transactionId);
    }
    limitedScanResult.setScanData(transactionIdSum);

    if (transactionIdSum.size() >= limit) {
      Long lastRowTimestamp = lastRowAccessor.getLastRowTimestamp();
      limitedScanResult.setLimitedTime(lastRowTimestamp);
      if (logger.isDebugEnabled()) {
        logger.debug("lastRowTimestamp lastTime:{}", DateUtils.longToDateStr(lastRowTimestamp));
      }
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "scanner start lastTime:{}", DateUtils.longToDateStr(area.getTimeRange().getFrom()));
      }
      limitedScanResult.setLimitedTime(area.getTimeRange().getFrom());
    }

    return limitedScanResult;
  }
    @Override
    public void handleLastResult(Result lastResult) {
      if (lastResult == null) {
        return;
      }

      Cell[] rawCells = lastResult.rawCells();
      Cell last = rawCells[rawCells.length - 1];
      byte[] row = CellUtil.cloneRow(last);
      byte[] originalRow = traceIdRowKeyDistributor.getOriginalKey(row);
      long reverseStartTime =
          BytesUtils.bytesToLong(originalRow, PinpointConstants.APPLICATION_NAME_MAX_LEN);
      this.lastRowTimestamp = TimeUtils.recoveryTimeMillis(reverseStartTime);

      byte[] qualifier = CellUtil.cloneQualifier(last);
      this.lastTransactionId = TransactionIdMapper.parseVarTransactionId(qualifier, 0);
      this.lastTransactionElapsed = BytesUtils.bytesToInt(qualifier, 0);

      if (logger.isDebugEnabled()) {
        logger.debug(
            "lastRowTimestamp={}, lastTransactionId={}, lastTransactionElapsed={}",
            DateUtils.longToDateStr(lastRowTimestamp),
            lastTransactionId,
            lastTransactionElapsed);
      }
    }