Repository: hbase Updated Branches: refs/heads/0.98 2a4fc5adf -> 6d5d0e237
HBASE-12363 Improve how KEEP_DELETED_CELLS works with MIN_VERSIONS. Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/6d5d0e23 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/6d5d0e23 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/6d5d0e23 Branch: refs/heads/0.98 Commit: 6d5d0e237b611e84871fe52bd492ee663ac56150 Parents: 2a4fc5a Author: Lars Hofhansl <la...@apache.org> Authored: Tue Nov 4 17:13:58 2014 -0800 Committer: Lars Hofhansl <la...@apache.org> Committed: Tue Nov 4 17:14:14 2014 -0800 ---------------------------------------------------------------------- .../apache/hadoop/hbase/HColumnDescriptor.java | 23 ++- .../apache/hadoop/hbase/KeepDeletedCells.java | 45 ++++++ .../hadoop/hbase/regionserver/ScanInfo.java | 7 +- .../hbase/regionserver/ScanQueryMatcher.java | 19 ++- .../org/apache/hadoop/hbase/HBaseTestCase.java | 2 +- .../hadoop/hbase/HBaseTestingUtility.java | 2 +- .../hadoop/hbase/TestHColumnDescriptor.java | 2 +- .../hbase/regionserver/TestKeepDeletes.java | 147 +++++++++++++++++-- .../hadoop/hbase/regionserver/TestMemStore.java | 8 +- .../hbase/regionserver/TestMinVersions.java | 19 ++- .../hbase/regionserver/TestQueryMatcher.java | 11 +- .../regionserver/TestReversibleScanners.java | 3 +- .../hbase/regionserver/TestStoreScanner.java | 9 +- hbase-shell/src/main/ruby/hbase/admin.rb | 2 +- 14 files changed, 251 insertions(+), 48 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-client/src/main/java/org/apache/hadoop/hbase/HColumnDescriptor.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/HColumnDescriptor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/HColumnDescriptor.java index 6638779..d84022b 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/HColumnDescriptor.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/HColumnDescriptor.java @@ -152,7 +152,7 @@ public class HColumnDescriptor implements WritableComparable<HColumnDescriptor> /** * Default setting for preventing deleted from being collected immediately. */ - public static final boolean DEFAULT_KEEP_DELETED = false; + public static final KeepDeletedCells DEFAULT_KEEP_DELETED = KeepDeletedCells.FALSE; /** * Default setting for whether to use a block cache or not. @@ -410,7 +410,7 @@ public class HColumnDescriptor implements WritableComparable<HColumnDescriptor> */ @Deprecated public HColumnDescriptor(final byte[] familyName, final int minVersions, - final int maxVersions, final boolean keepDeletedCells, + final int maxVersions, final KeepDeletedCells keepDeletedCells, final String compression, final boolean encodeOnDisk, final String dataBlockEncoding, final boolean inMemory, final boolean blockCacheEnabled, final int blocksize, @@ -754,10 +754,11 @@ public class HColumnDescriptor implements WritableComparable<HColumnDescriptor> return setValue(HConstants.IN_MEMORY, Boolean.toString(inMemory)); } - public boolean getKeepDeletedCells() { + public KeepDeletedCells getKeepDeletedCells() { String value = getValue(KEEP_DELETED_CELLS); if (value != null) { - return Boolean.valueOf(value).booleanValue(); + // toUpperCase for backwards compatibility + return KeepDeletedCells.valueOf(value.toUpperCase()); } return DEFAULT_KEEP_DELETED; } @@ -766,9 +767,21 @@ public class HColumnDescriptor implements WritableComparable<HColumnDescriptor> * @param keepDeletedCells True if deleted rows should not be collected * immediately. * @return this (for chained invocation) + * @deprecated use {@link #setKeepDeletedCells(KeepDeletedCells)} */ + @Deprecated public HColumnDescriptor setKeepDeletedCells(boolean keepDeletedCells) { - return setValue(KEEP_DELETED_CELLS, Boolean.toString(keepDeletedCells)); + return setValue(KEEP_DELETED_CELLS, (keepDeletedCells ? KeepDeletedCells.TRUE + : KeepDeletedCells.FALSE).toString()); + } + + /** + * @param keepDeletedCells True if deleted rows should not be collected + * immediately. + * @return this (for chained invocation) + */ + public HColumnDescriptor setKeepDeletedCells(KeepDeletedCells keepDeletedCells) { + return setValue(KEEP_DELETED_CELLS, keepDeletedCells.toString()); } /** http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-client/src/main/java/org/apache/hadoop/hbase/KeepDeletedCells.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/KeepDeletedCells.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/KeepDeletedCells.java new file mode 100644 index 0000000..6cd52e8 --- /dev/null +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/KeepDeletedCells.java @@ -0,0 +1,45 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase; + +/** + * Ways to keep cells marked for delete around. + */ +/* + * Don't change the TRUE/FALSE labels below, these have to be called + * this way for backwards compatibility. + */ +public enum KeepDeletedCells { + /** Deleted Cells are not retained. */ + FALSE, + /** + * Deleted Cells are retained until they are removed by other means + * such TTL or VERSIONS. + * If no TTL is specified or no new versions of delete cells are + * written, they are retained forever. + */ + TRUE, + /** + * Deleted Cells are retained until the delete marker expires due to TTL. + * This is useful when TTL is combined with MIN_VERSIONS and one + * wants to keep a minimum number of versions around but at the same + * time remove deleted cells after the TTL. + */ + TTL; +} http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanInfo.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanInfo.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanInfo.java index 1188ec8..a8b314e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanInfo.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanInfo.java @@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.regionserver; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.HColumnDescriptor; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.KeyValue.KVComparator; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.ClassSize; @@ -33,7 +34,7 @@ public class ScanInfo { private int minVersions; private int maxVersions; private long ttl; - private boolean keepDeletedCells; + private KeepDeletedCells keepDeletedCells; private long timeToPurgeDeletes; private KVComparator comparator; @@ -65,7 +66,7 @@ public class ScanInfo { * @param comparator The store's comparator */ public ScanInfo(final byte[] family, final int minVersions, final int maxVersions, - final long ttl, final boolean keepDeletedCells, final long timeToPurgeDeletes, + final long ttl, final KeepDeletedCells keepDeletedCells, final long timeToPurgeDeletes, final KVComparator comparator) { this.family = family; this.minVersions = minVersions; @@ -92,7 +93,7 @@ public class ScanInfo { return ttl; } - public boolean getKeepDeletedCells() { + public KeepDeletedCells getKeepDeletedCells() { return keepDeletedCells; } http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java index fae8678..98921f4 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java @@ -25,6 +25,7 @@ import java.util.NavigableSet; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.filter.Filter; @@ -70,7 +71,7 @@ public class ScanQueryMatcher { private boolean retainDeletesInOutput; /** whether to return deleted rows */ - private final boolean keepDeletedCells; + private final KeepDeletedCells keepDeletedCells; /** whether time range queries can see rows "behind" a delete */ private final boolean seePastDeleteMarkers; @@ -97,6 +98,7 @@ public class ScanQueryMatcher { * deleted KVs. */ private final long earliestPutTs; + private final long ttl; /** readPoint over which the KVs are unconditionally included */ protected long maxReadPointToTrackVersions; @@ -162,15 +164,18 @@ public class ScanQueryMatcher { this.earliestPutTs = earliestPutTs; this.maxReadPointToTrackVersions = readPointToUse; this.timeToPurgeDeletes = scanInfo.getTimeToPurgeDeletes(); + this.ttl = oldestUnexpiredTS; /* how to deal with deletes */ this.isUserScan = scanType == ScanType.USER_SCAN; // keep deleted cells: if compaction or raw scan - this.keepDeletedCells = (scanInfo.getKeepDeletedCells() && !isUserScan) || scan.isRaw(); - // retain deletes: if minor compaction or raw scan + this.keepDeletedCells = scan.isRaw() ? KeepDeletedCells.TRUE : + isUserScan ? KeepDeletedCells.FALSE : scanInfo.getKeepDeletedCells(); + // retain deletes: if minor compaction or raw scanisDone this.retainDeletesInOutput = scanType == ScanType.COMPACT_RETAIN_DELETES || scan.isRaw(); // seePastDeleteMarker: user initiated scans - this.seePastDeleteMarkers = scanInfo.getKeepDeletedCells() && isUserScan; + this.seePastDeleteMarkers = + scanInfo.getKeepDeletedCells() != KeepDeletedCells.FALSE && isUserScan; int maxVersions = scan.isRaw() ? scan.getMaxVersions() : Math.min(scan.getMaxVersions(), @@ -335,7 +340,8 @@ public class ScanQueryMatcher { */ byte type = bytes[initialOffset + keyLength - 1]; if (kv.isDelete()) { - if (!keepDeletedCells) { + if (keepDeletedCells == KeepDeletedCells.FALSE + || (keepDeletedCells == KeepDeletedCells.TTL && timestamp < ttl)) { // first ignore delete markers if the scanner can do so, and the // range does not include the marker // @@ -364,7 +370,8 @@ public class ScanQueryMatcher { // otherwise (i.e. a "raw" scan) we fall through to normal version and timerange checking return MatchCode.INCLUDE; } - } else if (keepDeletedCells) { + } else if (keepDeletedCells == KeepDeletedCells.TRUE + || (keepDeletedCells == KeepDeletedCells.TTL && timestamp >= ttl)) { if (timestamp < earliestPutTs) { // keeping delete rows, but there are no puts older than // this delete in the store files. http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestCase.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestCase.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestCase.java index d042f1c..8c1b20c 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestCase.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestCase.java @@ -205,7 +205,7 @@ public abstract class HBaseTestCase extends TestCase { * @return Column descriptor. */ protected HTableDescriptor createTableDescriptor(final String name, - final int minVersions, final int versions, final int ttl, boolean keepDeleted) { + final int minVersions, final int versions, final int ttl, KeepDeletedCells keepDeleted) { HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name)); for (byte[] cfName : new byte[][]{ fam1, fam2, fam3 }) { htd.addFamily(new HColumnDescriptor(cfName) http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java index 2bd0abc..9023e06 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java @@ -1559,7 +1559,7 @@ public class HBaseTestingUtility extends HBaseCommonTestingUtility { * @return Column descriptor. */ public HTableDescriptor createTableDescriptor(final String name, - final int minVersions, final int versions, final int ttl, boolean keepDeleted) { + final int minVersions, final int versions, final int ttl, KeepDeletedCells keepDeleted) { HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name)); for (byte[] cfName : new byte[][]{ fam1, fam2, fam3 }) { htd.addFamily(new HColumnDescriptor(cfName) http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHColumnDescriptor.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHColumnDescriptor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHColumnDescriptor.java index 90d5842..5ae32ec 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHColumnDescriptor.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHColumnDescriptor.java @@ -45,7 +45,7 @@ public class TestHColumnDescriptor { assertEquals(v, hcd.getMaxVersions()); hcd.setMinVersions(v); assertEquals(v, hcd.getMinVersions()); - hcd.setKeepDeletedCells(!HColumnDescriptor.DEFAULT_KEEP_DELETED); + hcd.setKeepDeletedCells(KeepDeletedCells.TRUE); hcd.setInMemory(!HColumnDescriptor.DEFAULT_IN_MEMORY); boolean inmemory = hcd.isInMemory(); hcd.setScope(v); http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java index 4f8794c..f8c48db 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java @@ -32,6 +32,7 @@ import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.SmallTests; import org.apache.hadoop.hbase.client.Delete; @@ -96,7 +97,7 @@ public class TestKeepDeletes { public void testBasicScenario() throws Exception { // keep 3 versions, rows do not expire HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 3, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -193,7 +194,7 @@ public class TestKeepDeletes { public void testRawScanWithoutKeepingDeletes() throws Exception { // KEEP_DELETED_CELLS is NOT enabled HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 3, - HConstants.FOREVER, false); + HConstants.FOREVER, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -238,7 +239,7 @@ public class TestKeepDeletes { public void testWithoutKeepingDeletes() throws Exception { // KEEP_DELETED_CELLS is NOT enabled HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 3, - HConstants.FOREVER, false); + HConstants.FOREVER, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -282,7 +283,7 @@ public class TestKeepDeletes { @Test public void testRawScanWithColumns() throws Exception { HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 3, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); Scan s = new Scan(); @@ -306,7 +307,7 @@ public class TestKeepDeletes { @Test public void testRawScan() throws Exception { HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 3, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -396,7 +397,7 @@ public class TestKeepDeletes { @Test public void testDeleteMarkerExpirationEmptyStore() throws Exception { HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 1, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -439,7 +440,7 @@ public class TestKeepDeletes { @Test public void testDeleteMarkerExpiration() throws Exception { HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 1, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -497,12 +498,90 @@ public class TestKeepDeletes { } /** + * Test delete marker removal from store files. + */ + @Test + public void testWithOldRow() throws Exception { + HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 1, + HConstants.FOREVER, KeepDeletedCells.TRUE); + HRegion region = hbu.createLocalHRegion(htd, null, null); + + long ts = EnvironmentEdgeManager.currentTimeMillis(); + + Put p = new Put(T1, ts); + p.add(c0, c0, T1); + region.put(p); + + // a put another (older) row in the same store + p = new Put(T2, ts-10); + p.add(c0, c0, T1); + region.put(p); + + // all the following deletes affect the put + Delete d = new Delete(T1, ts); + d.deleteColumns(c0, c0, ts); + region.delete(d); + + d = new Delete(T1, ts); + d.deleteFamily(c0, ts); + region.delete(d); + + d = new Delete(T1, ts); + d.deleteColumn(c0, c0, ts+1); + region.delete(d); + + d = new Delete(T1, ts); + d.deleteColumn(c0, c0, ts+2); + region.delete(d); + + // 1 family marker, 1 column marker, 2 version markers + assertEquals(4, countDeleteMarkers(region)); + + region.flushcache(); + assertEquals(4, countDeleteMarkers(region)); + region.compactStores(false); + assertEquals(4, countDeleteMarkers(region)); + + // another put will push out the earlier put... + p = new Put(T1, ts+3); + p.add(c0, c0, T1); + region.put(p); + + region.flushcache(); + // no markers are collected, since there is an affected put + region.compactStores(true); + assertEquals(4, countDeleteMarkers(region)); + + // all markers remain, since we have the older row + // and we haven't pushed the inlined markers past MAX_VERSIONS + region.compactStores(true); + assertEquals(4, countDeleteMarkers(region)); + + // another put will push out the earlier put... + p = new Put(T1, ts+4); + p.add(c0, c0, T1); + region.put(p); + + // this pushed out the column and version marker + // but the family markers remains. THIS IS A PROBLEM! + region.compactStores(true); + assertEquals(1, countDeleteMarkers(region)); + + // no amount of compacting is getting this of this one + // KEEP_DELETED_CELLS=>TTL is an option to avoid this. + region.compactStores(true); + assertEquals(1, countDeleteMarkers(region)); + + HRegion.closeHRegion(region); + } + + /** * Verify correct range demarcation */ @Test public void testRanges() throws Exception { HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 3, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -584,7 +663,7 @@ public class TestKeepDeletes { @Test public void testDeleteMarkerVersioning() throws Exception { HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 1, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -676,7 +755,7 @@ public class TestKeepDeletes { */ public void testWithMixedCFs() throws Exception { HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 0, 1, - HConstants.FOREVER, true); + HConstants.FOREVER, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis(); @@ -727,7 +806,8 @@ public class TestKeepDeletes { */ @Test public void testWithMinVersions() throws Exception { - HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 3, 1000, 1, true); + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 3, 1000, 1, KeepDeletedCells.TRUE); HRegion region = hbu.createLocalHRegion(htd, null, null); long ts = EnvironmentEdgeManager.currentTimeMillis() - 2000; // 2s in the past @@ -799,6 +879,51 @@ public class TestKeepDeletes { HRegion.closeHRegion(region); } + /** + * Test keeping deleted rows together with min versions set + * @throws Exception + */ + @Test + public void testWithTTL() throws Exception { + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 1, 1000, 1, KeepDeletedCells.TTL); + HRegion region = hbu.createLocalHRegion(htd, null, null); + + long ts = EnvironmentEdgeManager.currentTimeMillis() - 2000; // 2s in the past + + Put p = new Put(T1, ts); + p.add(c0, c0, T3); + region.put(p); + + // place an old row, to make the family marker expires anyway + p = new Put(T2, ts-10); + p.add(c0, c0, T1); + region.put(p); + + checkGet(region, T1, c0, c0, ts+1, T3); + // place a family delete marker + Delete d = new Delete(T1, ts+2); + region.delete(d); + + checkGet(region, T1, c0, c0, ts+1, T3); + + // 3 families, one column delete marker + assertEquals(3, countDeleteMarkers(region)); + + region.flushcache(); + // no delete marker removes by the flush + assertEquals(3, countDeleteMarkers(region)); + + // but the Put is gone + checkGet(region, T1, c0, c0, ts+1); + + region.compactStores(true); + // all delete marker gone + assertEquals(0, countDeleteMarkers(region)); + + HRegion.closeHRegion(region); + } + private void checkGet(HRegion region, byte[] row, byte[] fam, byte[] col, long time, byte[]... vals) throws IOException { Get g = new Get(row); http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStore.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStore.java index 3794ab6..61c12bc 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStore.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStore.java @@ -39,6 +39,7 @@ import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValueTestUtil; import org.apache.hadoop.hbase.MediumTests; @@ -93,8 +94,9 @@ public class TestMemStore extends TestCase { List<KeyValueScanner> memstorescanners = this.memstore.getScanners(0); Scan scan = new Scan(); List<Cell> result = new ArrayList<Cell>(); - ScanInfo scanInfo = new ScanInfo(null, 0, 1, HConstants.LATEST_TIMESTAMP, false, - 0, this.memstore.comparator); + ScanInfo scanInfo = + new ScanInfo(null, 0, 1, HConstants.LATEST_TIMESTAMP, KeepDeletedCells.FALSE, 0, + this.memstore.comparator); ScanType scanType = ScanType.USER_SCAN; StoreScanner s = new StoreScanner(scan, scanInfo, scanType, null, memstorescanners); int count = 0; @@ -511,7 +513,7 @@ public class TestMemStore extends TestCase { } //starting from each row, validate results should contain the starting row for (int startRowId = 0; startRowId < ROW_COUNT; startRowId++) { - ScanInfo scanInfo = new ScanInfo(FAMILY, 0, 1, Integer.MAX_VALUE, false, + ScanInfo scanInfo = new ScanInfo(FAMILY, 0, 1, Integer.MAX_VALUE, KeepDeletedCells.FALSE, 0, this.memstore.comparator); ScanType scanType = ScanType.USER_SCAN; InternalScanner scanner = new StoreScanner(new Scan( http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java index 73a712f..0992410 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java @@ -29,6 +29,7 @@ import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.SmallTests; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Get; @@ -64,7 +65,8 @@ public class TestMinVersions { */ @Test public void testGetClosestBefore() throws Exception { - HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 1, 1000, 1, false); + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 1, 1000, 1, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); try { @@ -113,7 +115,8 @@ public class TestMinVersions { @Test public void testStoreMemStore() throws Exception { // keep 3 versions minimum - HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 3, 1000, 1, false); + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 3, 1000, 1, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); // 2s in the past long ts = EnvironmentEdgeManager.currentTimeMillis() - 2000; @@ -167,7 +170,8 @@ public class TestMinVersions { */ @Test public void testDelete() throws Exception { - HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 3, 1000, 1, false); + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 3, 1000, 1, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); // 2s in the past @@ -225,7 +229,8 @@ public class TestMinVersions { */ @Test public void testMemStore() throws Exception { - HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 2, 1000, 1, false); + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 2, 1000, 1, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); // 2s in the past @@ -300,7 +305,8 @@ public class TestMinVersions { @Test public void testBaseCase() throws Exception { // 1 version minimum, 1000 versions maximum, ttl = 1s - HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 2, 1000, 1, false); + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 2, 1000, 1, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); try { @@ -391,7 +397,8 @@ public class TestMinVersions { */ @Test public void testFilters() throws Exception { - HTableDescriptor htd = hbu.createTableDescriptor(name.getMethodName(), 2, 1000, 1, false); + HTableDescriptor htd = + hbu.createTableDescriptor(name.getMethodName(), 2, 1000, 1, KeepDeletedCells.FALSE); HRegion region = hbu.createLocalHRegion(htd, null, null); final byte [] c1 = COLUMNS[1]; http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java index e8f5a5a..aafa710 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java @@ -29,6 +29,7 @@ import java.util.NavigableSet; import org.apache.hadoop.hbase.HBaseTestCase; import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue.KVComparator; import org.apache.hadoop.hbase.KeyValue.Type; @@ -93,7 +94,7 @@ public class TestQueryMatcher extends HBaseTestCase { private void _testMatch_ExplicitColumns(Scan scan, List<MatchCode> expected) throws IOException { // 2,4,5 ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(fam2, - 0, 1, ttl, false, 0, rowComparator), get.getFamilyMap().get(fam2), + 0, 1, ttl, KeepDeletedCells.FALSE, 0, rowComparator), get.getFamilyMap().get(fam2), EnvironmentEdgeManager.currentTimeMillis() - ttl); List<KeyValue> memstore = new ArrayList<KeyValue>(); @@ -175,7 +176,7 @@ public class TestQueryMatcher extends HBaseTestCase { expected.add(ScanQueryMatcher.MatchCode.DONE); ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(fam2, - 0, 1, ttl, false, 0, rowComparator), null, + 0, 1, ttl, KeepDeletedCells.FALSE, 0, rowComparator), null, EnvironmentEdgeManager.currentTimeMillis() - ttl); List<KeyValue> memstore = new ArrayList<KeyValue>(); @@ -229,7 +230,7 @@ public class TestQueryMatcher extends HBaseTestCase { long now = EnvironmentEdgeManager.currentTimeMillis(); ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(fam2, - 0, 1, testTTL, false, 0, rowComparator), get.getFamilyMap().get(fam2), + 0, 1, testTTL, KeepDeletedCells.FALSE, 0, rowComparator), get.getFamilyMap().get(fam2), now - testTTL); KeyValue [] kvs = new KeyValue[] { @@ -283,7 +284,7 @@ public class TestQueryMatcher extends HBaseTestCase { long now = EnvironmentEdgeManager.currentTimeMillis(); ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(fam2, - 0, 1, testTTL, false, 0, rowComparator), null, + 0, 1, testTTL, KeepDeletedCells.FALSE, 0, rowComparator), null, now - testTTL); KeyValue [] kvs = new KeyValue[] { @@ -338,7 +339,7 @@ public class TestQueryMatcher extends HBaseTestCase { byte[] from, byte[] to, byte[][] rows, MatchCode... expected) throws IOException { long now = EnvironmentEdgeManager.currentTimeMillis(); // Set time to purge deletes to negative value to avoid it ever happening. - ScanInfo scanInfo = new ScanInfo(fam2, 0, 1, ttl, false, -1L, rowComparator); + ScanInfo scanInfo = new ScanInfo(fam2, 0, 1, ttl, KeepDeletedCells.FALSE, -1L, rowComparator); NavigableSet<byte[]> cols = get.getFamilyMap().get(fam2); ScanQueryMatcher qm = new ScanQueryMatcher(scan, scanInfo, cols, Long.MAX_VALUE, http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestReversibleScanners.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestReversibleScanners.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestReversibleScanners.java index fa09263..f6532c6 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestReversibleScanners.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestReversibleScanners.java @@ -39,6 +39,7 @@ import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.MediumTests; import org.apache.hadoop.hbase.client.Durability; @@ -251,7 +252,7 @@ public class TestReversibleScanners { ScanType scanType = ScanType.USER_SCAN; ScanInfo scanInfo = new ScanInfo(FAMILYNAME, 0, Integer.MAX_VALUE, - Long.MAX_VALUE, false, 0, KeyValue.COMPARATOR); + Long.MAX_VALUE, KeepDeletedCells.FALSE, 0, KeyValue.COMPARATOR); // Case 1.Test a full reversed scan Scan scan = new Scan(); http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java index 05ac4b4..bd15a13 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java @@ -37,6 +37,7 @@ import junit.framework.TestCase; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.KeepDeletedCells; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValueTestUtil; import org.apache.hadoop.hbase.MediumTests; @@ -54,7 +55,7 @@ public class TestStoreScanner extends TestCase { private static final String CF_STR = "cf"; final byte [] CF = Bytes.toBytes(CF_STR); private ScanInfo scanInfo = new ScanInfo(CF, 0, Integer.MAX_VALUE, - Long.MAX_VALUE, false, 0, KeyValue.COMPARATOR); + Long.MAX_VALUE, KeepDeletedCells.FALSE, 0, KeyValue.COMPARATOR); private ScanType scanType = ScanType.USER_SCAN; public void setUp() throws Exception { @@ -422,7 +423,7 @@ public class TestStoreScanner extends TestCase { List<KeyValueScanner> scanners = scanFixture(kvs); Scan scan = new Scan(); scan.setMaxVersions(1); - ScanInfo scanInfo = new ScanInfo(CF, 0, 1, 500, false, 0, + ScanInfo scanInfo = new ScanInfo(CF, 0, 1, 500, KeepDeletedCells.FALSE, 0, KeyValue.COMPARATOR); ScanType scanType = ScanType.USER_SCAN; StoreScanner scanner = @@ -493,7 +494,7 @@ public class TestStoreScanner extends TestCase { Scan scan = new Scan(); scan.setMaxVersions(1); // scanner with ttl equal to 500 - ScanInfo scanInfo = new ScanInfo(CF, 0, 1, 500, false, 0, + ScanInfo scanInfo = new ScanInfo(CF, 0, 1, 500, KeepDeletedCells.FALSE, 0, KeyValue.COMPARATOR); ScanType scanType = ScanType.USER_SCAN; StoreScanner scanner = @@ -556,7 +557,7 @@ public class TestStoreScanner extends TestCase { ScanInfo scanInfo = new ScanInfo(Bytes.toBytes("cf"), 0 /* minVersions */, 2 /* maxVersions */, 500 /* ttl */, - false /* keepDeletedCells */, + KeepDeletedCells.FALSE /* keepDeletedCells */, 200, /* timeToPurgeDeletes */ KeyValue.COMPARATOR); StoreScanner scanner = http://git-wip-us.apache.org/repos/asf/hbase/blob/6d5d0e23/hbase-shell/src/main/ruby/hbase/admin.rb ---------------------------------------------------------------------- diff --git a/hbase-shell/src/main/ruby/hbase/admin.rb b/hbase-shell/src/main/ruby/hbase/admin.rb index b29536c..00a1a84 100644 --- a/hbase-shell/src/main/ruby/hbase/admin.rb +++ b/hbase-shell/src/main/ruby/hbase/admin.rb @@ -649,7 +649,7 @@ module Hbase family.setBlocksize(JInteger.valueOf(arg.delete(org.apache.hadoop.hbase.HColumnDescriptor::BLOCKSIZE))) if arg.include?(org.apache.hadoop.hbase.HColumnDescriptor::BLOCKSIZE) family.setMaxVersions(JInteger.valueOf(arg.delete(org.apache.hadoop.hbase.HColumnDescriptor::VERSIONS))) if arg.include?(org.apache.hadoop.hbase.HColumnDescriptor::VERSIONS) family.setMinVersions(JInteger.valueOf(arg.delete(org.apache.hadoop.hbase.HColumnDescriptor::MIN_VERSIONS))) if arg.include?(org.apache.hadoop.hbase.HColumnDescriptor::MIN_VERSIONS) - family.setKeepDeletedCells(JBoolean.valueOf(arg.delete(org.apache.hadoop.hbase.HColumnDescriptor::KEEP_DELETED_CELLS))) if arg.include?(org.apache.hadoop.hbase.HColumnDescriptor::KEEP_DELETED_CELLS) + family.setKeepDeletedCells(org.apache.hadoop.hbase.KeepDeletedCells.valueOf(arg.delete(org.apache.hadoop.hbase.HColumnDescriptor::KEEP_DELETED_CELLS).to_s.upcase)) if arg.include?(org.apache.hadoop.hbase.HColumnDescriptor::KEEP_DELETED_CELLS) family.setCompressTags(JBoolean.valueOf(arg.delete(org.apache.hadoop.hbase.HColumnDescriptor::COMPRESS_TAGS))) if arg.include?(org.apache.hadoop.hbase.HColumnDescriptor::COMPRESS_TAGS) family.setPrefetchBlocksOnOpen(JBoolean.valueOf(arg.delete(org.apache.hadoop.hbase.HColumnDescriptor::PREFETCH_BLOCKS_ON_OPEN))) if arg.include?(org.apache.hadoop.hbase.HColumnDescriptor::PREFETCH_BLOCKS_ON_OPEN) family.setValue(COMPRESSION_COMPACT, arg.delete(COMPRESSION_COMPACT)) if arg.include?(COMPRESSION_COMPACT)