Search in sources :

Example 6 with DeleteResult

use of org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker.DeleteResult in project hbase by apache.

the class TestScanDeleteTracker method testDeleteKeepVersionZero.

@Test
public void testDeleteKeepVersionZero() {
    byte[] qualifier = Bytes.toBytes("qualifier");
    long deleteTimestamp = 10;
    long valueTimestamp = 0;
    sdt.reset();
    KeyValue kv = new KeyValue(Bytes.toBytes("row"), Bytes.toBytes("f"), qualifier, deleteTimestamp, KeyValue.Type.Delete);
    sdt.add(kv);
    kv = new KeyValue(Bytes.toBytes("row"), Bytes.toBytes("f"), qualifier, valueTimestamp, KeyValue.Type.Delete);
    DeleteResult ret = sdt.isDeleted(kv);
    assertEquals(DeleteResult.NOT_DELETED, ret);
}
Also used : KeyValue(org.apache.hadoop.hbase.KeyValue) DeleteResult(org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker.DeleteResult) Test(org.junit.Test)

Example 7 with DeleteResult

use of org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker.DeleteResult in project hbase by apache.

the class TestScanDeleteTracker method testDeleteDeleteColumn.

@Test
public void testDeleteDeleteColumn() {
    byte[] qualifier = Bytes.toBytes("qualifier");
    KeyValue kv = new KeyValue(Bytes.toBytes("row"), Bytes.toBytes("f"), qualifier, timestamp, KeyValue.Type.Delete);
    sdt.add(kv);
    timestamp -= 5;
    kv = new KeyValue(Bytes.toBytes("row"), Bytes.toBytes("f"), qualifier, timestamp, KeyValue.Type.DeleteColumn);
    sdt.add(kv);
    timestamp -= 5;
    kv = new KeyValue(Bytes.toBytes("row"), Bytes.toBytes("f"), qualifier, timestamp, KeyValue.Type.DeleteColumn);
    DeleteResult ret = sdt.isDeleted(kv);
    assertEquals(DeleteResult.COLUMN_DELETED, ret);
}
Also used : KeyValue(org.apache.hadoop.hbase.KeyValue) DeleteResult(org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker.DeleteResult) Test(org.junit.Test)

Example 8 with DeleteResult

use of org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker.DeleteResult in project hbase by apache.

the class LegacyScanQueryMatcher method match.

@Override
public MatchCode match(Cell cell) throws IOException {
    if (filter != null && filter.filterAllRemaining()) {
        return MatchCode.DONE_SCAN;
    }
    MatchCode returnCode = preCheck(cell);
    if (returnCode != null) {
        return returnCode;
    }
    /*
     * The delete logic is pretty complicated now.
     * This is corroborated by the following:
     * 1. The store might be instructed to keep deleted rows around.
     * 2. A scan can optionally see past a delete marker now.
     * 3. If deleted rows are kept, we have to find out when we can
     *    remove the delete markers.
     * 4. Family delete markers are always first (regardless of their TS)
     * 5. Delete markers should not be counted as version
     * 6. Delete markers affect puts of the *same* TS
     * 7. Delete marker need to be version counted together with puts
     *    they affect
     */
    long timestamp = cell.getTimestamp();
    byte typeByte = cell.getTypeByte();
    long mvccVersion = cell.getSequenceId();
    if (CellUtil.isDelete(typeByte)) {
        if (keepDeletedCells == KeepDeletedCells.FALSE || (keepDeletedCells == KeepDeletedCells.TTL && timestamp < oldestUnexpiredTS)) {
            // first ignore delete markers if the scanner can do so, and the
            // range does not include the marker
            //
            // during flushes and compactions also ignore delete markers newer
            // than the readpoint of any open scanner, this prevents deleted
            // rows that could still be seen by a scanner from being collected
            boolean includeDeleteMarker = tr.withinOrAfterTimeRange(timestamp);
            if (includeDeleteMarker && mvccVersion <= maxReadPointToTrackVersions) {
                this.deletes.add(cell);
            }
        // Can't early out now, because DelFam come before any other keys
        }
        if (timeToPurgeDeletes > 0 && (EnvironmentEdgeManager.currentTime() - timestamp) <= timeToPurgeDeletes) {
            return MatchCode.INCLUDE;
        } else if (retainDeletesInOutput || mvccVersion > maxReadPointToTrackVersions) {
            // otherwise (i.e. a "raw" scan) we fall through to normal version and timerange checking
            return MatchCode.INCLUDE;
        } else if (keepDeletedCells == KeepDeletedCells.TRUE || (keepDeletedCells == KeepDeletedCells.TTL && timestamp >= oldestUnexpiredTS)) {
            if (timestamp < earliestPutTs) {
                // this delete in the store files.
                return columns.getNextRowOrNextColumn(cell);
            }
        // else: fall through and do version counting on the
        // delete markers
        } else {
            return MatchCode.SKIP;
        }
    // note the following next else if...
    // delete marker are not subject to other delete markers
    } else if (!this.deletes.isEmpty()) {
        DeleteResult deleteResult = deletes.isDeleted(cell);
        switch(deleteResult) {
            case FAMILY_DELETED:
            case COLUMN_DELETED:
                return columns.getNextRowOrNextColumn(cell);
            case VERSION_DELETED:
            case FAMILY_VERSION_DELETED:
                return MatchCode.SKIP;
            case NOT_DELETED:
                break;
            default:
                throw new RuntimeException("UNEXPECTED");
        }
    }
    int timestampComparison = tr.compare(timestamp);
    if (timestampComparison >= 1) {
        return MatchCode.SKIP;
    } else if (timestampComparison <= -1) {
        return columns.getNextRowOrNextColumn(cell);
    }
    // STEP 1: Check if the column is part of the requested columns
    MatchCode colChecker = columns.checkColumn(cell, typeByte);
    if (colChecker == MatchCode.INCLUDE) {
        ReturnCode filterResponse = ReturnCode.SKIP;
        // STEP 2: Yes, the column is part of the requested columns. Check if filter is present
        if (filter != null) {
            // STEP 3: Filter the key value and return if it filters out
            filterResponse = filter.filterKeyValue(cell);
            switch(filterResponse) {
                case SKIP:
                    return MatchCode.SKIP;
                case NEXT_COL:
                    return columns.getNextRowOrNextColumn(cell);
                case NEXT_ROW:
                    stickyNextRow = true;
                    return MatchCode.SEEK_NEXT_ROW;
                case SEEK_NEXT_USING_HINT:
                    return MatchCode.SEEK_NEXT_USING_HINT;
                default:
                    //It means it is either include or include and seek next
                    break;
            }
        }
        /*
       * STEP 4: Reaching this step means the column is part of the requested columns and either
       * the filter is null or the filter has returned INCLUDE or INCLUDE_AND_NEXT_COL response.
       * Now check the number of versions needed. This method call returns SKIP, INCLUDE,
       * INCLUDE_AND_SEEK_NEXT_ROW, INCLUDE_AND_SEEK_NEXT_COL.
       *
       * FilterResponse            ColumnChecker               Desired behavior
       * INCLUDE                   SKIP                        row has already been included, SKIP.
       * INCLUDE                   INCLUDE                     INCLUDE
       * INCLUDE                   INCLUDE_AND_SEEK_NEXT_COL   INCLUDE_AND_SEEK_NEXT_COL
       * INCLUDE                   INCLUDE_AND_SEEK_NEXT_ROW   INCLUDE_AND_SEEK_NEXT_ROW
       * INCLUDE_AND_SEEK_NEXT_COL SKIP                        row has already been included, SKIP.
       * INCLUDE_AND_SEEK_NEXT_COL INCLUDE                     INCLUDE_AND_SEEK_NEXT_COL
       * INCLUDE_AND_SEEK_NEXT_COL INCLUDE_AND_SEEK_NEXT_COL   INCLUDE_AND_SEEK_NEXT_COL
       * INCLUDE_AND_SEEK_NEXT_COL INCLUDE_AND_SEEK_NEXT_ROW   INCLUDE_AND_SEEK_NEXT_ROW
       *
       * In all the above scenarios, we return the column checker return value except for
       * FilterResponse (INCLUDE_AND_SEEK_NEXT_COL) and ColumnChecker(INCLUDE)
       */
        colChecker = columns.checkVersions(cell, timestamp, typeByte, mvccVersion > maxReadPointToTrackVersions);
        //Optimize with stickyNextRow
        boolean seekNextRowFromEssential = filterResponse == ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW && filter.isFamilyEssential(cell.getFamilyArray());
        if (colChecker == MatchCode.INCLUDE_AND_SEEK_NEXT_ROW || seekNextRowFromEssential) {
            stickyNextRow = true;
        }
        if (filterResponse == ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW) {
            if (colChecker != MatchCode.SKIP) {
                return MatchCode.INCLUDE_AND_SEEK_NEXT_ROW;
            }
            return MatchCode.SEEK_NEXT_ROW;
        }
        return (filterResponse == ReturnCode.INCLUDE_AND_NEXT_COL && colChecker == MatchCode.INCLUDE) ? MatchCode.INCLUDE_AND_SEEK_NEXT_COL : colChecker;
    }
    stickyNextRow = (colChecker == MatchCode.SEEK_NEXT_ROW) ? true : stickyNextRow;
    return colChecker;
}
Also used : ReturnCode(org.apache.hadoop.hbase.filter.Filter.ReturnCode) DeleteResult(org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker.DeleteResult)

Aggregations

DeleteResult (org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker.DeleteResult)8 KeyValue (org.apache.hadoop.hbase.KeyValue)7 Test (org.junit.Test)7 ReturnCode (org.apache.hadoop.hbase.filter.Filter.ReturnCode)1