diff --git a/CHANGES.txt b/CHANGES.txt index c35bc1ee08b..c2547d7355c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -87,6 +87,7 @@ Release 0.91.0 - Unreleased needs an upper bound added (Ted Yu via Stack) HBASE-3676 Update region server load for AssignmentManager through regionServerReport() (Ted Yu via Stack) + HBASE-3468 Enhance checkAndPut and checkAndDelete with comparators TASK HBASE-3559 Move report of split to master OFF the heartbeat channel diff --git a/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java b/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java index ac1e230c548..92d941accfe 100644 --- a/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java +++ b/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java @@ -27,6 +27,8 @@ import org.apache.hadoop.hbase.client.Increment; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.InternalScanner; import org.apache.hadoop.hbase.regionserver.wal.HLogKey; @@ -136,32 +138,32 @@ public abstract class BaseRegionObserverCoprocessor implements RegionObserver { @Override public boolean preCheckAndPut(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Put put, final boolean result) - throws IOException { + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Put put, final boolean result) throws IOException { return result; } @Override public boolean postCheckAndPut(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Put put, final boolean result) - throws IOException { + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Put put, final boolean result) throws IOException { return result; } @Override public boolean preCheckAndDelete(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Delete delete, final boolean result) - throws IOException { + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Delete delete, final boolean result) throws IOException { return result; } @Override public boolean postCheckAndDelete(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Delete delete, final boolean result) - throws IOException { + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Delete delete, final boolean result) throws IOException { return result; } diff --git a/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java b/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java index fe8775b97d3..ae93a0a12be 100644 --- a/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java +++ b/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java @@ -27,7 +27,8 @@ import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.Increment; -import org.apache.hadoop.hbase.coprocessor.CoprocessorEnvironment; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.InternalScanner; import org.apache.hadoop.hbase.regionserver.wal.HLogKey; @@ -285,7 +286,8 @@ public interface RegionObserver extends Coprocessor { * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param put data to put if check succeeds * @param result * @return the return value to return to client if bypassing default @@ -294,7 +296,8 @@ public interface RegionObserver extends Coprocessor { */ public boolean preCheckAndPut(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Put put, final boolean result) + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Put put, final boolean result) throws IOException; /** @@ -306,7 +309,8 @@ public interface RegionObserver extends Coprocessor { * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param put data to put if check succeeds * @param result from the checkAndPut * @return the possibly transformed return value to return to client @@ -314,7 +318,8 @@ public interface RegionObserver extends Coprocessor { */ public boolean postCheckAndPut(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Put put, final boolean result) + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Put put, final boolean result) throws IOException; /** @@ -328,7 +333,8 @@ public interface RegionObserver extends Coprocessor { * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param delete delete to commit if check succeeds * @param result * @return the value to return to client if bypassing default processing @@ -336,7 +342,8 @@ public interface RegionObserver extends Coprocessor { */ public boolean preCheckAndDelete(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Delete delete, final boolean result) + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Delete delete, final boolean result) throws IOException; /** @@ -348,7 +355,8 @@ public interface RegionObserver extends Coprocessor { * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param delete delete to commit if check succeeds * @param result from the CheckAndDelete * @return the possibly transformed returned value to return to client @@ -356,7 +364,8 @@ public interface RegionObserver extends Coprocessor { */ public boolean postCheckAndDelete(final RegionCoprocessorEnvironment e, final byte [] row, final byte [] family, final byte [] qualifier, - final byte [] value, final Delete delete, final boolean result) + final CompareOp compareOp, final WritableByteArrayComparable comparator, + final Delete delete, final boolean result) throws IOException; /** diff --git a/src/main/java/org/apache/hadoop/hbase/filter/NullComparator.java b/src/main/java/org/apache/hadoop/hbase/filter/NullComparator.java new file mode 100644 index 00000000000..1d372065a0a --- /dev/null +++ b/src/main/java/org/apache/hadoop/hbase/filter/NullComparator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * 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.filter; + +/** + * A binary comparator which lexicographically compares against the specified + * byte array using {@link org.apache.hadoop.hbase.util.Bytes#compareTo(byte[], byte[])}. + */ +public class NullComparator extends WritableByteArrayComparable { + + /** Nullary constructor for Writable, do not use */ + public NullComparator() { + value = new byte[0]; + } + + @Override + public int compareTo(byte[] value) { + return value != null ? 1 : 0; + } + +} diff --git a/src/main/java/org/apache/hadoop/hbase/filter/QualifierFilter.java b/src/main/java/org/apache/hadoop/hbase/filter/QualifierFilter.java index 2625eb11d5b..43bf526e0ce 100644 --- a/src/main/java/org/apache/hadoop/hbase/filter/QualifierFilter.java +++ b/src/main/java/org/apache/hadoop/hbase/filter/QualifierFilter.java @@ -46,12 +46,12 @@ public class QualifierFilter extends CompareFilter { /** * Constructor. - * @param qualifierCompareOp the compare op for column qualifier matching + * @param op the compare op for column qualifier matching * @param qualifierComparator the comparator for column qualifier matching */ - public QualifierFilter(final CompareOp qualifierCompareOp, + public QualifierFilter(final CompareOp op, final WritableByteArrayComparable qualifierComparator) { - super(qualifierCompareOp, qualifierComparator); + super(op, qualifierComparator); } @Override diff --git a/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java b/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java index 7b8f193a37a..f397f41a4cd 100644 --- a/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java +++ b/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java @@ -65,6 +65,7 @@ import org.apache.hadoop.hbase.filter.BitComparator; import org.apache.hadoop.hbase.filter.ColumnCountGetFilter; import org.apache.hadoop.hbase.filter.ColumnPrefixFilter; import org.apache.hadoop.hbase.filter.CompareFilter; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; import org.apache.hadoop.hbase.filter.DependentColumnFilter; import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter; import org.apache.hadoop.hbase.filter.InclusiveStopFilter; @@ -219,6 +220,8 @@ public class HbaseObjectWritable implements Writable, WritableWithSize, Configur addToMap(Serializable.class, code++); addToMap(RandomRowFilter.class, code++); + + addToMap(CompareOp.class, code++); } private Class declaredClass; diff --git a/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java b/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java index be8abc1be90..663cab526df 100644 --- a/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java +++ b/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java @@ -40,6 +40,8 @@ import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.coprocessor.Exec; import org.apache.hadoop.hbase.client.coprocessor.ExecResult; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.regionserver.wal.HLog; import org.apache.hadoop.ipc.RemoteException; import org.apache.hadoop.ipc.VersionedProtocol; @@ -435,4 +437,44 @@ public interface HRegionInterface extends VersionedProtocol, Stoppable, Abortabl */ ExecResult execCoprocessor(byte[] regionName, Exec call) throws IOException; + + /** + * Atomically checks if a row/family/qualifier value match the expectedValue. + * If it does, it adds the put. If passed expected value is null, then the + * check is for non-existance of the row/column. + * + * @param regionName + * @param row + * @param family + * @param qualifier + * @param compareOp + * @param comparator + * @param put + * @throws IOException + * @return true if the new put was execute, false otherwise + */ + public boolean checkAndPut(final byte[] regionName, final byte[] row, + final byte[] family, final byte[] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, final Put put) + throws IOException; + + /** + * Atomically checks if a row/family/qualifier value match the expectedValue. + * If it does, it adds the delete. If passed expected value is null, then the + * check is for non-existance of the row/column. + * + * @param regionName + * @param row + * @param family + * @param qualifier + * @param compareOp + * @param comparator + * @param delete + * @throws IOException + * @return true if the new put was execute, false otherwise + */ + public boolean checkAndDelete(final byte[] regionName, final byte[] row, + final byte[] family, final byte[] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, final Delete delete) + throws IOException; } diff --git a/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index 3549c255989..36eadb27205 100644 --- a/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ b/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -74,8 +74,10 @@ import org.apache.hadoop.hbase.client.RowLock; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.coprocessor.Exec; import org.apache.hadoop.hbase.client.coprocessor.ExecResult; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.filter.IncompatibleFilterException; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.io.HeapSize; import org.apache.hadoop.hbase.io.TimeRange; import org.apache.hadoop.hbase.io.hfile.BlockCache; @@ -1635,14 +1637,16 @@ public class HRegion implements HeapSize { // , Writable{ * @param row * @param family * @param qualifier - * @param expectedValue + * @param compareOp + * @param comparator * @param lockId * @param writeToWAL * @throws IOException * @return true if the new put was execute, false otherwise */ public boolean checkAndMutate(byte [] row, byte [] family, byte [] qualifier, - byte [] expectedValue, Writable w, Integer lockId, boolean writeToWAL) + CompareOp compareOp, WritableByteArrayComparable comparator, Writable w, + Integer lockId, boolean writeToWAL) throws IOException{ checkReadOnly(); //TODO, add check for value length or maybe even better move this to the @@ -1671,12 +1675,32 @@ public class HRegion implements HeapSize { // , Writable{ boolean matches = false; if (result.size() == 0 && - (expectedValue == null || expectedValue.length == 0)) { + (comparator.getValue() == null || comparator.getValue().length == 0)) { matches = true; } else if (result.size() == 1) { - //Compare the expected value with the actual value - byte [] actualValue = result.get(0).getValue(); - matches = Bytes.equals(expectedValue, actualValue); + int compareResult = comparator.compareTo(result.get(0).getValue()); + switch (compareOp) { + case LESS: + matches = compareResult <= 0; + break; + case LESS_OR_EQUAL: + matches = compareResult < 0; + break; + case EQUAL: + matches = compareResult == 0; + break; + case NOT_EQUAL: + matches = compareResult != 0; + break; + case GREATER_OR_EQUAL: + matches = compareResult > 0; + break; + case GREATER: + matches = compareResult >= 0; + break; + default: + throw new RuntimeException("Unknown Compare op " + compareOp.name()); + } } //If matches put the new put or delete the new delete if (matches) { diff --git a/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java b/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java index b894f35c51e..991f5dc73f5 100644 --- a/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java +++ b/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java @@ -34,7 +34,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -96,6 +95,9 @@ import org.apache.hadoop.hbase.client.coprocessor.Exec; import org.apache.hadoop.hbase.client.coprocessor.ExecResult; import org.apache.hadoop.hbase.executor.ExecutorService; import org.apache.hadoop.hbase.executor.ExecutorService.ExecutorType; +import org.apache.hadoop.hbase.filter.BinaryComparator; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.io.hfile.LruBlockCache; import org.apache.hadoop.hbase.io.hfile.LruBlockCache.CacheStats; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; @@ -1694,8 +1696,9 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler, } private boolean checkAndMutate(final byte[] regionName, final byte[] row, - final byte[] family, final byte[] qualifier, final byte[] value, - final Writable w, Integer lock) throws IOException { + final byte[] family, final byte[] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, final Writable w, + Integer lock) throws IOException { checkOpen(); this.requestCount.incrementAndGet(); HRegion region = getRegion(regionName); @@ -1703,8 +1706,8 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler, if (!region.getRegionInfo().isMetaTable()) { this.cacheFlusher.reclaimMemStoreMemory(); } - return region - .checkAndMutate(row, family, qualifier, value, w, lock, true); + return region.checkAndMutate(row, family, qualifier, compareOp, + comparator, w, lock, true); } catch (Throwable t) { throw convertThrowableToIOE(cleanup(t)); } @@ -1731,18 +1734,59 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler, + "regionName is null"); } HRegion region = getRegion(regionName); + WritableByteArrayComparable comparator = new BinaryComparator(value); if (region.getCoprocessorHost() != null) { Boolean result = region.getCoprocessorHost() - .preCheckAndPut(row, family, qualifier, value, put); + .preCheckAndPut(row, family, qualifier, CompareOp.EQUAL, comparator, + put); if (result != null) { return result.booleanValue(); } } boolean result = checkAndMutate(regionName, row, family, qualifier, - value, put, getLockFromId(put.getLockId())); + CompareOp.EQUAL, new BinaryComparator(value), put, + getLockFromId(put.getLockId())); if (region.getCoprocessorHost() != null) { result = region.getCoprocessorHost().postCheckAndPut(row, family, - qualifier, value, put, result); + qualifier, CompareOp.EQUAL, comparator, put, result); + } + return result; + } + + /** + * + * @param regionName + * @param row + * @param family + * @param qualifier + * @param compareOp + * @param comparator + * @param put + * @throws IOException + * @return true if the new put was execute, false otherwise + */ + public boolean checkAndPut(final byte[] regionName, final byte[] row, + final byte[] family, final byte[] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, final Put put) + throws IOException { + checkOpen(); + if (regionName == null) { + throw new IOException("Invalid arguments to checkAndPut " + + "regionName is null"); + } + HRegion region = getRegion(regionName); + if (region.getCoprocessorHost() != null) { + Boolean result = region.getCoprocessorHost() + .preCheckAndPut(row, family, qualifier, compareOp, comparator, put); + if (result != null) { + return result.booleanValue(); + } + } + boolean result = checkAndMutate(regionName, row, family, qualifier, + compareOp, comparator, put, getLockFromId(put.getLockId())); + if (region.getCoprocessorHost() != null) { + result = region.getCoprocessorHost().postCheckAndPut(row, family, + qualifier, compareOp, comparator, put, result); } return result; } @@ -1769,22 +1813,62 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler, + "regionName is null"); } HRegion region = getRegion(regionName); + WritableByteArrayComparable comparator = new BinaryComparator(value); if (region.getCoprocessorHost() != null) { Boolean result = region.getCoprocessorHost().preCheckAndDelete(row, - family, qualifier, value, delete); + family, qualifier, CompareOp.EQUAL, comparator, delete); if (result != null) { return result.booleanValue(); } } - boolean result = checkAndMutate(regionName, row, family, qualifier, value, - delete, getLockFromId(delete.getLockId())); + boolean result = checkAndMutate(regionName, row, family, qualifier, + CompareOp.EQUAL, comparator, delete, getLockFromId(delete.getLockId())); if (region.getCoprocessorHost() != null) { result = region.getCoprocessorHost().postCheckAndDelete(row, family, - qualifier, value, delete, result); + qualifier, CompareOp.EQUAL, comparator, delete, result); } return result; } + /** + * + * @param regionName + * @param row + * @param family + * @param qualifier + * @param compareOp + * @param comparator + * @param delete + * @throws IOException + * @return true if the new put was execute, false otherwise + */ + public boolean checkAndDelete(final byte[] regionName, final byte[] row, + final byte[] family, final byte[] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, final Delete delete) + throws IOException { + checkOpen(); + + if (regionName == null) { + throw new IOException("Invalid arguments to checkAndDelete " + + "regionName is null"); + } + HRegion region = getRegion(regionName); + if (region.getCoprocessorHost() != null) { + Boolean result = region.getCoprocessorHost().preCheckAndDelete(row, + family, qualifier, compareOp, comparator, delete); + if (result != null) { + return result.booleanValue(); + } + } + boolean result = checkAndMutate(regionName, row, family, qualifier, + compareOp, comparator, delete, getLockFromId(delete.getLockId())); + if (region.getCoprocessorHost() != null) { + result = region.getCoprocessorHost().postCheckAndDelete(row, family, + qualifier, compareOp, comparator, delete, result); + } + return result; + } + // // remote scanner interface // diff --git a/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java b/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java index cb8a6f91a90..7fd56076287 100644 --- a/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java +++ b/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java @@ -24,32 +24,22 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.*; -import org.apache.hadoop.hbase.client.coprocessor.Batch; -import org.apache.hadoop.hbase.client.coprocessor.Batch.Call; -import org.apache.hadoop.hbase.client.coprocessor.Batch.Callback; import org.apache.hadoop.hbase.coprocessor.*; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; import org.apache.hadoop.hbase.regionserver.wal.HLogKey; import org.apache.hadoop.hbase.regionserver.wal.WALEdit; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.VersionInfo; import org.apache.hadoop.util.StringUtils; -import java.io.File; import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -619,14 +609,16 @@ public class RegionCoprocessorHost * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param put data to put if check succeeds * @return true or false to return to client if default processing should * be bypassed, or null otherwise * @throws IOException e */ public Boolean preCheckAndPut(final byte [] row, final byte [] family, - final byte [] qualifier, final byte [] value, Put put) + final byte [] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, Put put) throws IOException { try { @@ -636,7 +628,7 @@ public class RegionCoprocessorHost for (RegionEnvironment env: coprocessors) { if (env.getInstance() instanceof RegionObserver) { result = ((RegionObserver)env.getInstance()).preCheckAndPut(env, row, family, - qualifier, value, put, result); + qualifier, compareOp, comparator, put, result); bypass |= env.shouldBypass(); if (env.shouldComplete()) { break; @@ -653,12 +645,14 @@ public class RegionCoprocessorHost * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param put data to put if check succeeds * @throws IOException e */ public boolean postCheckAndPut(final byte [] row, final byte [] family, - final byte [] qualifier, final byte [] value, final Put put, + final byte [] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, final Put put, boolean result) throws IOException { @@ -667,7 +661,7 @@ public class RegionCoprocessorHost for (RegionEnvironment env: coprocessors) { if (env.getInstance() instanceof RegionObserver) { result = ((RegionObserver)env.getInstance()).postCheckAndPut(env, row, - family, qualifier, value, put, result); + family, qualifier, compareOp, comparator, put, result); if (env.shouldComplete()) { break; } @@ -683,16 +677,17 @@ public class RegionCoprocessorHost * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param delete delete to commit if check succeeds * @return true or false to return to client if default processing should * be bypassed, or null otherwise * @throws IOException e */ public Boolean preCheckAndDelete(final byte [] row, final byte [] family, - final byte [] qualifier, final byte [] value, Delete delete) - throws IOException - { + final byte [] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, Delete delete) + throws IOException { try { boolean bypass = false; boolean result = false; @@ -700,7 +695,7 @@ public class RegionCoprocessorHost for (RegionEnvironment env: coprocessors) { if (env.getInstance() instanceof RegionObserver) { result = ((RegionObserver)env.getInstance()).preCheckAndDelete(env, row, - family, qualifier, value, delete, result); + family, qualifier, compareOp, comparator, delete, result); bypass |= env.shouldBypass(); if (env.shouldComplete()) { break; @@ -717,12 +712,14 @@ public class RegionCoprocessorHost * @param row row to check * @param family column family * @param qualifier column qualifier - * @param value the expected value + * @param compareOp the comparison operation + * @param comparator the comparator * @param delete delete to commit if check succeeds * @throws IOException e */ public boolean postCheckAndDelete(final byte [] row, final byte [] family, - final byte [] qualifier, final byte [] value, final Delete delete, + final byte [] qualifier, final CompareOp compareOp, + final WritableByteArrayComparable comparator, final Delete delete, boolean result) throws IOException { @@ -730,8 +727,9 @@ public class RegionCoprocessorHost coprocessorLock.readLock().lock(); for (RegionEnvironment env: coprocessors) { if (env.getInstance() instanceof RegionObserver) { - result = ((RegionObserver)env.getInstance()).postCheckAndDelete(env, row, - family, qualifier, value, delete, result); + result = ((RegionObserver)env.getInstance()) + .postCheckAndDelete(env, row, family, qualifier, compareOp, + comparator, delete, result); if (env.shouldComplete()) { break; } diff --git a/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java b/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java index bf3817f15a0..e106b45ce04 100644 --- a/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java +++ b/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java @@ -53,10 +53,10 @@ import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.filter.BinaryComparator; import org.apache.hadoop.hbase.filter.ColumnCountGetFilter; -import org.apache.hadoop.hbase.filter.CompareFilter; import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.filter.FilterList; +import org.apache.hadoop.hbase.filter.NullComparator; import org.apache.hadoop.hbase.filter.PrefixFilter; import org.apache.hadoop.hbase.filter.SingleColumnValueFilter; import org.apache.hadoop.hbase.regionserver.HRegion.RegionScanner; @@ -461,43 +461,47 @@ public class TestHRegion extends HBaseTestCase { put.add(fam1, qf1, val1); //checkAndPut with correct value - boolean res = region.checkAndMutate(row1, fam1, qf1, emptyVal, put, lockId, - true); + boolean res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(emptyVal), put, lockId, true); assertTrue(res); // not empty anymore - res = region.checkAndMutate(row1, fam1, qf1, emptyVal, put, lockId, true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(emptyVal), put, lockId, true); assertFalse(res); Delete delete = new Delete(row1); delete.deleteColumn(fam1, qf1); - res = region.checkAndMutate(row1, fam1, qf1, emptyVal, delete, lockId, - true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(emptyVal), delete, lockId, true); assertFalse(res); put = new Put(row1); put.add(fam1, qf1, val2); //checkAndPut with correct value - res = region.checkAndMutate(row1, fam1, qf1, val1, put, lockId, true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val1), put, lockId, true); assertTrue(res); //checkAndDelete with correct value delete = new Delete(row1); delete.deleteColumn(fam1, qf1); delete.deleteColumn(fam1, qf1); - res = region.checkAndMutate(row1, fam1, qf1, val2, delete, lockId, true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val2), delete, lockId, true); assertTrue(res); delete = new Delete(row1); - res = region.checkAndMutate(row1, fam1, qf1, emptyVal, delete, lockId, - true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(emptyVal), delete, lockId, true); assertTrue(res); //checkAndPut looking for a null value put = new Put(row1); put.add(fam1, qf1, val1); - res = region.checkAndMutate(row1, fam1, qf1, null, put, lockId, true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new NullComparator(), put, lockId, true); assertTrue(res); } @@ -521,13 +525,15 @@ public class TestHRegion extends HBaseTestCase { region.put(put); //checkAndPut with wrong value - boolean res = region.checkAndMutate(row1, fam1, qf1, val2, put, lockId, true); + boolean res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val2), put, lockId, true); assertEquals(false, res); //checkAndDelete with wrong value Delete delete = new Delete(row1); delete.deleteFamily(fam1); - res = region.checkAndMutate(row1, fam1, qf1, val2, delete, lockId, true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val2), delete, lockId, true); assertEquals(false, res); } @@ -549,13 +555,15 @@ public class TestHRegion extends HBaseTestCase { region.put(put); //checkAndPut with correct value - boolean res = region.checkAndMutate(row1, fam1, qf1, val1, put, lockId, true); + boolean res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val1), put, lockId, true); assertEquals(true, res); //checkAndDelete with correct value Delete delete = new Delete(row1); delete.deleteColumn(fam1, qf1); - res = region.checkAndMutate(row1, fam1, qf1, val1, put, lockId, true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val1), put, lockId, true); assertEquals(true, res); } @@ -590,7 +598,8 @@ public class TestHRegion extends HBaseTestCase { Store store = region.getStore(fam1); store.memstore.kvset.size(); - boolean res = region.checkAndMutate(row1, fam1, qf1, val1, put, lockId, true); + boolean res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val1), put, lockId, true); assertEquals(true, res); store.memstore.kvset.size(); @@ -613,8 +622,8 @@ public class TestHRegion extends HBaseTestCase { Put put = new Put(row2); put.add(fam1, qual1, value1); try { - boolean res = region.checkAndMutate(row, - fam1, qual1, value2, put, null, false); + boolean res = region.checkAndMutate(row, fam1, qual1, CompareOp.EQUAL, + new BinaryComparator(value2), put, null, false); fail(); } catch (DoNotRetryIOException expected) { // expected exception. @@ -660,8 +669,8 @@ public class TestHRegion extends HBaseTestCase { delete.deleteColumn(fam1, qf1); delete.deleteColumn(fam2, qf1); delete.deleteColumn(fam1, qf3); - boolean res = region.checkAndMutate(row1, fam1, qf1, val2, delete, lockId, - true); + boolean res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val2), delete, lockId, true); assertEquals(true, res); Get get = new Get(row1); @@ -676,8 +685,8 @@ public class TestHRegion extends HBaseTestCase { //Family delete delete = new Delete(row1); delete.deleteFamily(fam2); - res = region.checkAndMutate(row1, fam2, qf1, emptyVal, delete, lockId, - true); + res = region.checkAndMutate(row1, fam2, qf1, CompareOp.EQUAL, + new BinaryComparator(emptyVal), delete, lockId, true); assertEquals(true, res); get = new Get(row1); @@ -687,8 +696,8 @@ public class TestHRegion extends HBaseTestCase { //Row delete delete = new Delete(row1); - res = region.checkAndMutate(row1, fam1, qf1, val1, delete, lockId, - true); + res = region.checkAndMutate(row1, fam1, qf1, CompareOp.EQUAL, + new BinaryComparator(val1), delete, lockId, true); assertEquals(true, res); get = new Get(row1); r = region.get(get, null); @@ -2389,7 +2398,7 @@ public class TestHRegion extends HBaseTestCase { Scan scan = new Scan(); scan.addFamily(family); scan.setFilter(new SingleColumnValueFilter(family, qual1, - CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(5L)))); + CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(5L)))); int expectedCount = 0; List res = new ArrayList(); @@ -2753,10 +2762,9 @@ public class TestHRegion extends HBaseTestCase { idxScan.addFamily(family); idxScan.setFilter(new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(new SingleColumnValueFilter(family, qual1, - CompareFilter.CompareOp.GREATER_OR_EQUAL, + CompareOp.GREATER_OR_EQUAL, new BinaryComparator(Bytes.toBytes(0L))), - new SingleColumnValueFilter(family, qual1, - CompareFilter.CompareOp.LESS_OR_EQUAL, + new SingleColumnValueFilter(family, qual1, CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes(3L))) ))); InternalScanner scanner = region.getScanner(idxScan);