View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver.querymatcher;
19  
20  import static org.apache.hadoop.hbase.regionserver.querymatcher.ScanQueryMatcher.MatchCode.INCLUDE;
21  import static org.apache.hadoop.hbase.regionserver.querymatcher.ScanQueryMatcher.MatchCode.SKIP;
22  import static org.junit.Assert.assertEquals;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.KeepDeletedCells;
32  import org.apache.hadoop.hbase.KeyValue;
33  import org.apache.hadoop.hbase.KeyValue.Type;
34  import org.apache.hadoop.hbase.KeyValueUtil;
35  import org.apache.hadoop.hbase.regionserver.ScanInfo;
36  import org.apache.hadoop.hbase.regionserver.ScanType;
37  import org.apache.hadoop.hbase.regionserver.querymatcher.ScanQueryMatcher.MatchCode;
38  import org.apache.hadoop.hbase.testclassification.RegionServerTests;
39  import org.apache.hadoop.hbase.testclassification.SmallTests;
40  import org.apache.hadoop.hbase.util.Bytes;
41  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
42  import org.junit.Test;
43  import org.junit.experimental.categories.Category;
44  
45  @Category({ RegionServerTests.class, SmallTests.class })
46  public class TestCompactionScanQueryMatcher extends AbstractTestScanQueryMatcher {
47  
48    private static final Log LOG = LogFactory.getLog(TestCompactionScanQueryMatcher.class);
49  
50    @Test
51    public void testMatch_PartialRangeDropDeletes() throws Exception {
52      // Some ranges.
53      testDropDeletes(row2, row3, new byte[][] { row1, row2, row2, row3 }, INCLUDE, SKIP, SKIP,
54        INCLUDE);
55      testDropDeletes(row2, row3, new byte[][] { row1, row1, row2 }, INCLUDE, INCLUDE, SKIP);
56      testDropDeletes(row2, row3, new byte[][] { row2, row3, row3 }, SKIP, INCLUDE, INCLUDE);
57      testDropDeletes(row1, row3, new byte[][] { row1, row2, row3 }, SKIP, SKIP, INCLUDE);
58      // Open ranges.
59      testDropDeletes(HConstants.EMPTY_START_ROW, row3, new byte[][] { row1, row2, row3 }, SKIP, SKIP,
60        INCLUDE);
61      testDropDeletes(row2, HConstants.EMPTY_END_ROW, new byte[][] { row1, row2, row3 }, INCLUDE,
62        SKIP, SKIP);
63      testDropDeletes(HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW,
64        new byte[][] { row1, row2, row3, row3 }, SKIP, SKIP, SKIP, SKIP);
65  
66      // No KVs in range.
67      testDropDeletes(row2, row3, new byte[][] { row1, row1, row3 }, INCLUDE, INCLUDE, INCLUDE);
68      testDropDeletes(row2, row3, new byte[][] { row3, row3 }, INCLUDE, INCLUDE);
69      testDropDeletes(row2, row3, new byte[][] { row1, row1 }, INCLUDE, INCLUDE);
70    }
71  
72    private void testDropDeletes(byte[] from, byte[] to, byte[][] rows, MatchCode... expected)
73        throws IOException {
74      long now = EnvironmentEdgeManager.currentTime();
75      // Set time to purge deletes to negative value to avoid it ever happening.
76      ScanInfo scanInfo = new ScanInfo(this.conf, fam2, 0, 1, ttl, KeepDeletedCells.FALSE, -1L,
77          rowComparator);
78  
79      CompactionScanQueryMatcher qm = CompactionScanQueryMatcher.create(scanInfo,
80        ScanType.COMPACT_RETAIN_DELETES, Long.MAX_VALUE, HConstants.OLDEST_TIMESTAMP,
81        HConstants.OLDEST_TIMESTAMP, now, from, to, null);
82      List<ScanQueryMatcher.MatchCode> actual = new ArrayList<ScanQueryMatcher.MatchCode>(
83          rows.length);
84      byte[] prevRow = null;
85      for (byte[] row : rows) {
86        if (prevRow == null || !Bytes.equals(prevRow, row)) {
87          qm.setToNewRow(KeyValueUtil.createFirstOnRow(row));
88          prevRow = row;
89        }
90        actual.add(qm.match(new KeyValue(row, fam2, null, now, Type.Delete)));
91      }
92  
93      assertEquals(expected.length, actual.size());
94      for (int i = 0; i < expected.length; i++) {
95        LOG.debug("expected " + expected[i] + ", actual " + actual.get(i));
96        assertEquals(expected[i], actual.get(i));
97      }
98    }
99  }