HBASE-6769 HRS.multi eats NoSuchColumnFamilyException (Elliott Clark)
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1384377 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
476a274729
commit
786a5213c9
|
@ -39,6 +39,7 @@ public final class HConstants {
|
||||||
public enum OperationStatusCode {
|
public enum OperationStatusCode {
|
||||||
NOT_RUN,
|
NOT_RUN,
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
|
BAD_FAMILY,
|
||||||
SANITY_CHECK_FAILURE,
|
SANITY_CHECK_FAILURE,
|
||||||
FAILURE;
|
FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown if a mutation fails sanity checks.
|
||||||
|
*/
|
||||||
|
public class FailedSanityCheckException extends DoNotRetryIOException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1788783640409186240L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default constructor
|
||||||
|
*/
|
||||||
|
public FailedSanityCheckException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public FailedSanityCheckException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
* @param cause
|
||||||
|
*/
|
||||||
|
public FailedSanityCheckException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -73,6 +73,7 @@ import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.fs.permission.FsPermission;
|
import org.apache.hadoop.fs.permission.FsPermission;
|
||||||
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
||||||
import org.apache.hadoop.hbase.DroppedSnapshotException;
|
import org.apache.hadoop.hbase.DroppedSnapshotException;
|
||||||
|
import org.apache.hadoop.hbase.FailedSanityCheckException;
|
||||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
|
@ -2155,10 +2156,16 @@ public class HRegion implements HeapSize { // , Writable{
|
||||||
} else {
|
} else {
|
||||||
prepareDelete((Delete) mutation);
|
prepareDelete((Delete) mutation);
|
||||||
}
|
}
|
||||||
} catch (DoNotRetryIOException dnrioe) {
|
} catch (NoSuchColumnFamilyException nscf) {
|
||||||
LOG.warn("No such column family in batch mutation", dnrioe);
|
LOG.warn("No such column family in batch mutation", nscf);
|
||||||
batchOp.retCodeDetails[lastIndexExclusive] = new OperationStatus(
|
batchOp.retCodeDetails[lastIndexExclusive] = new OperationStatus(
|
||||||
OperationStatusCode.SANITY_CHECK_FAILURE, dnrioe.getMessage());
|
OperationStatusCode.BAD_FAMILY, nscf.getMessage());
|
||||||
|
lastIndexExclusive++;
|
||||||
|
continue;
|
||||||
|
} catch (FailedSanityCheckException fsce) {
|
||||||
|
LOG.warn("Batch Mutation did not pass sanity check", fsce);
|
||||||
|
batchOp.retCodeDetails[lastIndexExclusive] = new OperationStatus(
|
||||||
|
OperationStatusCode.SANITY_CHECK_FAILURE, fsce.getMessage());
|
||||||
lastIndexExclusive++;
|
lastIndexExclusive++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2731,7 +2738,7 @@ public class HRegion implements HeapSize { // , Writable{
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkTimestamps(final Map<byte[], List<KeyValue>> familyMap,
|
void checkTimestamps(final Map<byte[], List<KeyValue>> familyMap,
|
||||||
long now) throws DoNotRetryIOException {
|
long now) throws FailedSanityCheckException {
|
||||||
if (timestampSlop == HConstants.LATEST_TIMESTAMP) {
|
if (timestampSlop == HConstants.LATEST_TIMESTAMP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2740,7 +2747,7 @@ public class HRegion implements HeapSize { // , Writable{
|
||||||
for (KeyValue kv : kvs) {
|
for (KeyValue kv : kvs) {
|
||||||
// see if the user-side TS is out of range. latest = server-side
|
// see if the user-side TS is out of range. latest = server-side
|
||||||
if (!kv.isLatestTimestamp() && kv.getTimestamp() > maxTs) {
|
if (!kv.isLatestTimestamp() && kv.getTimestamp() > maxTs) {
|
||||||
throw new DoNotRetryIOException("Timestamp for KV out of range "
|
throw new FailedSanityCheckException("Timestamp for KV out of range "
|
||||||
+ kv + " (too.new=" + timestampSlop + ")");
|
+ kv + " (too.new=" + timestampSlop + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.hbase.Chore;
|
import org.apache.hadoop.hbase.Chore;
|
||||||
import org.apache.hadoop.hbase.ClockOutOfSyncException;
|
import org.apache.hadoop.hbase.ClockOutOfSyncException;
|
||||||
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
||||||
|
import org.apache.hadoop.hbase.FailedSanityCheckException;
|
||||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.HConstants.OperationStatusCode;
|
import org.apache.hadoop.hbase.HConstants.OperationStatusCode;
|
||||||
|
@ -3922,10 +3923,27 @@ public class HRegionServer implements ClientProtocol,
|
||||||
|
|
||||||
OperationStatus codes[] = region.batchMutate(mutationsWithLocks);
|
OperationStatus codes[] = region.batchMutate(mutationsWithLocks);
|
||||||
for (i = 0; i < codes.length; i++) {
|
for (i = 0; i < codes.length; i++) {
|
||||||
if (codes[i].getOperationStatusCode() != OperationStatusCode.SUCCESS) {
|
switch (codes[i].getOperationStatusCode()) {
|
||||||
|
case BAD_FAMILY:
|
||||||
|
result = ResponseConverter.buildActionResult(
|
||||||
|
new NoSuchColumnFamilyException(codes[i].getExceptionMsg()));
|
||||||
|
builder.setResult(i, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SANITY_CHECK_FAILURE:
|
||||||
|
result = ResponseConverter.buildActionResult(
|
||||||
|
new FailedSanityCheckException(codes[i].getExceptionMsg()));
|
||||||
|
builder.setResult(i, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
result = ResponseConverter.buildActionResult(
|
result = ResponseConverter.buildActionResult(
|
||||||
new DoNotRetryIOException(codes[i].getExceptionMsg()));
|
new DoNotRetryIOException(codes[i].getExceptionMsg()));
|
||||||
builder.setResult(i, result);
|
builder.setResult(i, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUCCESS:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ie) {
|
} catch (IOException ie) {
|
||||||
|
|
|
@ -66,6 +66,7 @@ import org.apache.hadoop.hbase.io.hfile.BlockCache;
|
||||||
import org.apache.hadoop.hbase.io.hfile.CacheConfig;
|
import org.apache.hadoop.hbase.io.hfile.CacheConfig;
|
||||||
import org.apache.hadoop.hbase.regionserver.HRegion;
|
import org.apache.hadoop.hbase.regionserver.HRegion;
|
||||||
import org.apache.hadoop.hbase.regionserver.HRegionServer;
|
import org.apache.hadoop.hbase.regionserver.HRegionServer;
|
||||||
|
import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException;
|
||||||
import org.apache.hadoop.hbase.regionserver.Store;
|
import org.apache.hadoop.hbase.regionserver.Store;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
|
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
|
||||||
|
@ -3682,6 +3683,25 @@ public class TestFromClientSide {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPutNoCF() throws IOException {
|
||||||
|
final byte[] BAD_FAM = Bytes.toBytes("BAD_CF");
|
||||||
|
final byte[] VAL = Bytes.toBytes(100);
|
||||||
|
HTable table = TEST_UTIL.createTable(Bytes.toBytes("testPutNoCF"), new byte[][]{FAMILY});
|
||||||
|
|
||||||
|
boolean caughtNSCFE = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Put p = new Put(ROW);
|
||||||
|
p.add(BAD_FAM, QUALIFIER, VAL);
|
||||||
|
table.put(p);
|
||||||
|
} catch (RetriesExhaustedWithDetailsException e) {
|
||||||
|
caughtNSCFE = e.getCause(0) instanceof NoSuchColumnFamilyException;
|
||||||
|
}
|
||||||
|
assertTrue("Should throw NoSuchColumnFamilyException", caughtNSCFE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRowsPut() throws IOException {
|
public void testRowsPut() throws IOException {
|
||||||
final byte[] CONTENTS_FAMILY = Bytes.toBytes("contents");
|
final byte[] CONTENTS_FAMILY = Bytes.toBytes("contents");
|
||||||
|
@ -4274,6 +4294,8 @@ public class TestFromClientSide {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIncrement() throws Exception {
|
public void testIncrement() throws Exception {
|
||||||
LOG.info("Starting testIncrement");
|
LOG.info("Starting testIncrement");
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.hadoop.fs.FSDataOutputStream;
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
||||||
|
import org.apache.hadoop.hbase.FailedSanityCheckException;
|
||||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
import org.apache.hadoop.hbase.HBaseTestCase;
|
import org.apache.hadoop.hbase.HBaseTestCase;
|
||||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
|
@ -575,7 +576,7 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
boolean exception = false;
|
boolean exception = false;
|
||||||
try {
|
try {
|
||||||
this.region.put(p);
|
this.region.put(p);
|
||||||
} catch (DoNotRetryIOException e) {
|
} catch (NoSuchColumnFamilyException e) {
|
||||||
exception = true;
|
exception = true;
|
||||||
}
|
}
|
||||||
assertTrue(exception);
|
assertTrue(exception);
|
||||||
|
@ -616,7 +617,7 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
codes = this.region.put(puts);
|
codes = this.region.put(puts);
|
||||||
assertEquals(10, codes.length);
|
assertEquals(10, codes.length);
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
assertEquals((i == 5) ? OperationStatusCode.SANITY_CHECK_FAILURE :
|
assertEquals((i == 5) ? OperationStatusCode.BAD_FAMILY :
|
||||||
OperationStatusCode.SUCCESS, codes[i].getOperationStatusCode());
|
OperationStatusCode.SUCCESS, codes[i].getOperationStatusCode());
|
||||||
}
|
}
|
||||||
assertEquals(1, HLog.getSyncTime().count);
|
assertEquals(1, HLog.getSyncTime().count);
|
||||||
|
@ -654,7 +655,7 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
assertEquals(1, HLog.getSyncTime().count);
|
assertEquals(1, HLog.getSyncTime().count);
|
||||||
codes = retFromThread.get();
|
codes = retFromThread.get();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
assertEquals((i == 5) ? OperationStatusCode.SANITY_CHECK_FAILURE :
|
assertEquals((i == 5) ? OperationStatusCode.BAD_FAMILY :
|
||||||
OperationStatusCode.SUCCESS, codes[i].getOperationStatusCode());
|
OperationStatusCode.SUCCESS, codes[i].getOperationStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,7 +672,7 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
codes = region.batchMutate(putsAndLocks.toArray(new Pair[0]));
|
codes = region.batchMutate(putsAndLocks.toArray(new Pair[0]));
|
||||||
LOG.info("...performed put");
|
LOG.info("...performed put");
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
assertEquals((i == 5) ? OperationStatusCode.SANITY_CHECK_FAILURE :
|
assertEquals((i == 5) ? OperationStatusCode.BAD_FAMILY :
|
||||||
OperationStatusCode.SUCCESS, codes[i].getOperationStatusCode());
|
OperationStatusCode.SUCCESS, codes[i].getOperationStatusCode());
|
||||||
}
|
}
|
||||||
// Make sure we didn't do an extra batch
|
// Make sure we didn't do an extra batch
|
||||||
|
@ -687,6 +688,45 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBatchPutWithTsSlop() throws Exception {
|
||||||
|
byte[] b = Bytes.toBytes(getName());
|
||||||
|
byte[] cf = Bytes.toBytes(COLUMN_FAMILY);
|
||||||
|
byte[] qual = Bytes.toBytes("qual");
|
||||||
|
byte[] val = Bytes.toBytes("val");
|
||||||
|
|
||||||
|
HBaseConfiguration conf = new HBaseConfiguration();
|
||||||
|
|
||||||
|
|
||||||
|
// add data with a timestamp that is too recent for range. Ensure assert
|
||||||
|
conf.setInt("hbase.hregion.keyvalue.timestamp.slop.millisecs", 1000);
|
||||||
|
this.region = initHRegion(b, getName(), conf, cf);
|
||||||
|
|
||||||
|
try{
|
||||||
|
HLog.getSyncTime(); // clear counter from prior tests
|
||||||
|
assertEquals(0, HLog.getSyncTime().count);
|
||||||
|
|
||||||
|
final Put[] puts = new Put[10];
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
puts[i] = new Put(Bytes.toBytes("row_" + i), Long.MAX_VALUE - 100);
|
||||||
|
puts[i].add(cf, qual, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
OperationStatus[] codes = this.region.put(puts);
|
||||||
|
assertEquals(10, codes.length);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assertEquals(OperationStatusCode.SANITY_CHECK_FAILURE, codes[i]
|
||||||
|
.getOperationStatusCode());
|
||||||
|
}
|
||||||
|
assertEquals(0, HLog.getSyncTime().count);
|
||||||
|
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
HRegion.closeHRegion(this.region);
|
||||||
|
this.region = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// checkAndMutate tests
|
// checkAndMutate tests
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1219,6 +1259,7 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that there is server-side filtering for invalid timestamp upper
|
* Tests that there is server-side filtering for invalid timestamp upper
|
||||||
* bound. Note that the timestamp lower bound is automatically handled for us
|
* bound. Note that the timestamp lower bound is automatically handled for us
|
||||||
|
@ -1234,6 +1275,7 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
// add data with a timestamp that is too recent for range. Ensure assert
|
// add data with a timestamp that is too recent for range. Ensure assert
|
||||||
conf.setInt("hbase.hregion.keyvalue.timestamp.slop.millisecs", 1000);
|
conf.setInt("hbase.hregion.keyvalue.timestamp.slop.millisecs", 1000);
|
||||||
this.region = initHRegion(tableName, method, conf, families);
|
this.region = initHRegion(tableName, method, conf, families);
|
||||||
|
boolean caughtExcep = false;
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
// no TS specified == use latest. should not error
|
// no TS specified == use latest. should not error
|
||||||
|
@ -1244,9 +1286,11 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
System.currentTimeMillis() + 2000,
|
System.currentTimeMillis() + 2000,
|
||||||
Bytes.toBytes("value")), false);
|
Bytes.toBytes("value")), false);
|
||||||
fail("Expected IOE for TS out of configured timerange");
|
fail("Expected IOE for TS out of configured timerange");
|
||||||
} catch (DoNotRetryIOException ioe) {
|
} catch (FailedSanityCheckException ioe) {
|
||||||
LOG.debug("Received expected exception", ioe);
|
LOG.debug("Received expected exception", ioe);
|
||||||
|
caughtExcep = true;
|
||||||
}
|
}
|
||||||
|
assertTrue("Should catch FailedSanityCheckException", caughtExcep);
|
||||||
} finally {
|
} finally {
|
||||||
HRegion.closeHRegion(this.region);
|
HRegion.closeHRegion(this.region);
|
||||||
this.region = null;
|
this.region = null;
|
||||||
|
|
Loading…
Reference in New Issue