HBASE-17734 Guard against possibly copying the qualifier in the ScanDeleteTracker

Signed-off-by: tedyu <yuzhihong@gmail.com>
This commit is contained in:
ChiaPing Tsai 2017-03-07 01:20:34 +08:00 committed by tedyu
parent 4beae9a56e
commit 81cb298014
6 changed files with 51 additions and 25 deletions

View File

@ -55,6 +55,12 @@ public abstract class CompactionScanQueryMatcher extends ScanQueryMatcher {
this.keepDeletedCells = scanInfo.getKeepDeletedCells(); this.keepDeletedCells = scanInfo.getKeepDeletedCells();
} }
@Override
public void beforeShipped() throws IOException {
super.beforeShipped();
deletes.beforeShipped();
}
@Override @Override
public boolean hasNullColumnInQuery() { public boolean hasNullColumnInQuery() {
return true; return true;

View File

@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.regionserver.querymatcher;
import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.regionserver.ShipperListener;
/** /**
* This interface is used for the tracking and enforcement of Deletes during the course of a Get or * This interface is used for the tracking and enforcement of Deletes during the course of a Get or
@ -32,7 +33,7 @@ import org.apache.hadoop.hbase.Cell;
* </ul> * </ul>
*/ */
@InterfaceAudience.Private @InterfaceAudience.Private
public interface DeleteTracker { public interface DeleteTracker extends ShipperListener {
/** /**
* Add the specified cell to the list of deletes to check against for this row operation. * Add the specified cell to the list of deletes to check against for this row operation.

View File

@ -147,6 +147,12 @@ public class LegacyScanQueryMatcher extends ScanQueryMatcher {
this.dropDeletesToRow = Preconditions.checkNotNull(dropDeletesToRow); this.dropDeletesToRow = Preconditions.checkNotNull(dropDeletesToRow);
} }
@Override
public void beforeShipped() throws IOException {
super.beforeShipped();
deletes.beforeShipped();
}
@Override @Override
public MatchCode match(Cell cell) throws IOException { public MatchCode match(Cell cell) throws IOException {
if (filter != null && filter.filterAllRemaining()) { if (filter != null && filter.filterAllRemaining()) {

View File

@ -50,6 +50,12 @@ public abstract class NormalUserScanQueryMatcher extends UserScanQueryMatcher {
this.seePastDeleteMarkers = scanInfo.getKeepDeletedCells() != KeepDeletedCells.FALSE; this.seePastDeleteMarkers = scanInfo.getKeepDeletedCells() != KeepDeletedCells.FALSE;
} }
@Override
public void beforeShipped() throws IOException {
super.beforeShipped();
deletes.beforeShipped();
}
@Override @Override
public MatchCode match(Cell cell) throws IOException { public MatchCode match(Cell cell) throws IOException {
if (filter != null && filter.filterAllRemaining()) { if (filter != null && filter.filterAllRemaining()) {

View File

@ -18,6 +18,7 @@
package org.apache.hadoop.hbase.regionserver.querymatcher; package org.apache.hadoop.hbase.regionserver.querymatcher;
import java.io.IOException;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@ -26,6 +27,7 @@ import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellComparator; import org.apache.hadoop.hbase.CellComparator;
import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.KeyValueUtil;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
/** /**
@ -48,9 +50,7 @@ public class ScanDeleteTracker implements DeleteTracker {
protected boolean hasFamilyStamp = false; protected boolean hasFamilyStamp = false;
protected long familyStamp = 0L; protected long familyStamp = 0L;
protected SortedSet<Long> familyVersionStamps = new TreeSet<Long>(); protected SortedSet<Long> familyVersionStamps = new TreeSet<Long>();
protected byte[] deleteBuffer = null; protected Cell deleteCell = null;
protected int deleteOffset = 0;
protected int deleteLength = 0;
protected byte deleteType = 0; protected byte deleteType = 0;
protected long deleteTimestamp = 0L; protected long deleteTimestamp = 0L;
@ -74,16 +74,14 @@ public class ScanDeleteTracker implements DeleteTracker {
return; return;
} }
if (deleteBuffer != null && type < deleteType) { if (deleteCell != null && type < deleteType) {
// same column, so ignore less specific delete // same column, so ignore less specific delete
if (CellUtil.matchingQualifier(cell, deleteBuffer, deleteOffset, deleteLength)) { if (CellUtil.matchingQualifier(cell, deleteCell)) {
return; return;
} }
} }
// new column, or more general delete type // new column, or more general delete type
deleteBuffer = cell.getQualifierArray(); deleteCell = cell;
deleteOffset = cell.getQualifierOffset();
deleteLength = cell.getQualifierLength();
deleteType = type; deleteType = type;
deleteTimestamp = timestamp; deleteTimestamp = timestamp;
} }
@ -106,8 +104,8 @@ public class ScanDeleteTracker implements DeleteTracker {
return DeleteResult.FAMILY_VERSION_DELETED; return DeleteResult.FAMILY_VERSION_DELETED;
} }
if (deleteBuffer != null) { if (deleteCell != null) {
int ret = -(CellComparator.compareQualifiers(cell, deleteBuffer, deleteOffset, deleteLength)); int ret = -(CellComparator.compareQualifiers(cell, deleteCell));
if (ret == 0) { if (ret == 0) {
if (deleteType == KeyValue.Type.DeleteColumn.getCode()) { if (deleteType == KeyValue.Type.DeleteColumn.getCode()) {
return DeleteResult.COLUMN_DELETED; return DeleteResult.COLUMN_DELETED;
@ -121,13 +119,15 @@ public class ScanDeleteTracker implements DeleteTracker {
assert timestamp < deleteTimestamp; assert timestamp < deleteTimestamp;
// different timestamp, let's clear the buffer. // different timestamp, let's clear the buffer.
deleteBuffer = null; deleteCell = null;
} else if (ret < 0) { } else if (ret < 0) {
// Next column case. // Next column case.
deleteBuffer = null; deleteCell = null;
} else { } else {
throw new IllegalStateException("isDelete failed: deleteBuffer=" throw new IllegalStateException("isDelete failed: deleteBuffer="
+ Bytes.toStringBinary(deleteBuffer, deleteOffset, deleteLength) + ", qualifier=" + Bytes.toStringBinary(deleteCell.getQualifierArray(),
deleteCell.getQualifierOffset(), deleteCell.getQualifierLength())
+ ", qualifier="
+ Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(), + Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(),
cell.getQualifierLength()) cell.getQualifierLength())
+ ", timestamp=" + timestamp + ", comparison result: " + ret); + ", timestamp=" + timestamp + ", comparison result: " + ret);
@ -139,7 +139,7 @@ public class ScanDeleteTracker implements DeleteTracker {
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return deleteBuffer == null && !hasFamilyStamp && familyVersionStamps.isEmpty(); return deleteCell == null && !hasFamilyStamp && familyVersionStamps.isEmpty();
} }
@Override @Override
@ -148,7 +148,7 @@ public class ScanDeleteTracker implements DeleteTracker {
hasFamilyStamp = false; hasFamilyStamp = false;
familyStamp = 0L; familyStamp = 0L;
familyVersionStamps.clear(); familyVersionStamps.clear();
deleteBuffer = null; deleteCell = null;
} }
@Override @Override
@ -156,4 +156,11 @@ public class ScanDeleteTracker implements DeleteTracker {
public void update() { public void update() {
this.reset(); this.reset();
} }
@Override
public void beforeShipped() throws IOException {
if (deleteCell != null) {
deleteCell = KeyValueUtil.toNewKeyCell(deleteCell);
}
}
} }

View File

@ -87,8 +87,8 @@ public class VisibilityScanDeleteTracker extends ScanDeleteTracker {
return; return;
} }
// new column, or more general delete type // new column, or more general delete type
if (deleteBuffer != null) { if (deleteCell != null) {
if (!(CellUtil.matchingQualifier(delCell, deleteBuffer, deleteOffset, deleteLength))) { if (!(CellUtil.matchingQualifier(delCell, deleteCell))) {
// A case where there are deletes for a column qualifier but there are // A case where there are deletes for a column qualifier but there are
// no corresponding puts for them. Rare case. // no corresponding puts for them. Rare case.
visibilityTagsDeleteColumns = null; visibilityTagsDeleteColumns = null;
@ -104,9 +104,7 @@ public class VisibilityScanDeleteTracker extends ScanDeleteTracker {
visiblityTagsDeleteColumnVersion = null; visiblityTagsDeleteColumnVersion = null;
} }
} }
deleteBuffer = delCell.getQualifierArray(); deleteCell = delCell;
deleteOffset = delCell.getQualifierOffset();
deleteLength = delCell.getQualifierLength();
deleteType = type; deleteType = type;
deleteTimestamp = timestamp; deleteTimestamp = timestamp;
extractDeleteCellVisTags(delCell, KeyValue.Type.codeToType(type)); extractDeleteCellVisTags(delCell, KeyValue.Type.codeToType(type));
@ -243,8 +241,8 @@ public class VisibilityScanDeleteTracker extends ScanDeleteTracker {
} }
} }
} }
if (deleteBuffer != null) { if (deleteCell != null) {
int ret = CellComparator.compareQualifiers(cell, deleteBuffer, deleteOffset, deleteLength); int ret = CellComparator.compareQualifiers(cell, deleteCell);
if (ret == 0) { if (ret == 0) {
if (deleteType == KeyValue.Type.DeleteColumn.getCode()) { if (deleteType == KeyValue.Type.DeleteColumn.getCode()) {
if (visibilityTagsDeleteColumns != null) { if (visibilityTagsDeleteColumns != null) {
@ -304,13 +302,15 @@ public class VisibilityScanDeleteTracker extends ScanDeleteTracker {
} }
} else if (ret > 0) { } else if (ret > 0) {
// Next column case. // Next column case.
deleteBuffer = null; deleteCell = null;
// Can nullify this because we are moving to the next column // Can nullify this because we are moving to the next column
visibilityTagsDeleteColumns = null; visibilityTagsDeleteColumns = null;
visiblityTagsDeleteColumnVersion = null; visiblityTagsDeleteColumnVersion = null;
} else { } else {
throw new IllegalStateException("isDeleted failed: deleteBuffer=" throw new IllegalStateException("isDeleted failed: deleteBuffer="
+ Bytes.toStringBinary(deleteBuffer, deleteOffset, deleteLength) + ", qualifier=" + Bytes.toStringBinary(deleteCell.getQualifierArray(),
deleteCell.getQualifierOffset(), deleteCell.getQualifierLength())
+ ", qualifier="
+ Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(), + Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(),
cell.getQualifierLength()) cell.getQualifierLength())
+ ", timestamp=" + timestamp + ", comparison result: " + ret); + ", timestamp=" + timestamp + ", comparison result: " + ret);