private Scan createScan(String applicationName, Range range, boolean scanBackward) { Scan scan = new Scan(); scan.setCaching(this.scanCacheSize); byte[] bApplicationName = Bytes.toBytes(applicationName); byte[] traceIndexStartKey = SpanUtils.getTraceIndexRowKey(bApplicationName, range.getFrom()); byte[] traceIndexEndKey = SpanUtils.getTraceIndexRowKey(bApplicationName, range.getTo()); if (scanBackward) { // start key is replaced by end key because key has been reversed scan.setStartRow(traceIndexEndKey); scan.setStopRow(traceIndexStartKey); } else { scan.setReversed(true); scan.setStartRow(traceIndexStartKey); scan.setStopRow(traceIndexEndKey); } scan.addFamily(HBaseTables.APPLICATION_TRACE_INDEX_CF_TRACE); scan.setId("ApplicationTraceIndexScan"); // toString() method of Scan converts a message to json format so it is slow for the first time. logger.trace("create scan:{}", scan); return scan; }
public static Scan newScan(Scan scan) { try { Scan newScan = new Scan(scan); // Clone the underlying family map instead of sharing it between // the existing and cloned Scan (which is the retarded default // behavior). TreeMap<byte[], NavigableSet<byte[]>> existingMap = (TreeMap<byte[], NavigableSet<byte[]>>) scan.getFamilyMap(); Map<byte[], NavigableSet<byte[]>> clonedMap = new TreeMap<byte[], NavigableSet<byte[]>>(existingMap); newScan.setFamilyMap(clonedMap); // Carry over the reversed attribute newScan.setReversed(scan.isReversed()); newScan.setSmall(scan.isSmall()); return newScan; } catch (IOException e) { throw new RuntimeException(e); } }
// Start/stop row must be swapped if scan is being done in reverse public static void setupReverseScan(Scan scan) { if (isReversed(scan)) { byte[] startRow = scan.getStartRow(); byte[] stopRow = scan.getStopRow(); byte[] newStartRow = startRow; byte[] newStopRow = stopRow; if (startRow.length != 0) { /* * Must get previous key because this is going from an inclusive start key to an exclusive stop key, and * we need the start key to be included. We get the previous key by decrementing the last byte by one. * However, with variable length data types, we need to fill with the max byte value, otherwise, if the * start key is 'ab', we lower it to 'aa' which would cause 'aab' to be included (which isn't correct). * So we fill with a 0xFF byte to prevent this. A single 0xFF would be enough for our primitive types (as * that byte wouldn't occur), but for an arbitrary VARBINARY key we can't know how many bytes to tack * on. It's lame of HBase to force us to do this. */ newStartRow = Arrays.copyOf(startRow, startRow.length + MAX_FILL_LENGTH_FOR_PREVIOUS_KEY.length); if (ByteUtil.previousKey(newStartRow, startRow.length)) { System.arraycopy( MAX_FILL_LENGTH_FOR_PREVIOUS_KEY, 0, newStartRow, startRow.length, MAX_FILL_LENGTH_FOR_PREVIOUS_KEY.length); } else { newStartRow = HConstants.EMPTY_START_ROW; } } if (stopRow.length != 0) { // Must add null byte because we need the start to be exclusive while it was inclusive newStopRow = ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY); } scan.setStartRow(newStopRow); scan.setStopRow(newStartRow); scan.setReversed(true); } }