001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client;
019
020import static org.apache.hadoop.hbase.util.Threads.sleep;
021import static org.junit.Assert.assertTrue;
022
023import java.io.IOException;
024import java.util.List;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.hadoop.fs.FileSystem;
027import org.apache.hadoop.fs.Path;
028import org.apache.hadoop.hbase.Cell;
029import org.apache.hadoop.hbase.HBaseClassTestRule;
030import org.apache.hadoop.hbase.HBaseTestingUtility;
031import org.apache.hadoop.hbase.HConstants;
032import org.apache.hadoop.hbase.TableName;
033import org.apache.hadoop.hbase.io.ByteBuffAllocator;
034import org.apache.hadoop.hbase.io.DeallocateRewriteByteBuffAllocator;
035import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
036import org.apache.hadoop.hbase.io.hfile.BlockCacheFactory;
037import org.apache.hadoop.hbase.regionserver.HRegion;
038import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
039import org.apache.hadoop.hbase.regionserver.RegionServerServices;
040import org.apache.hadoop.hbase.testclassification.LargeTests;
041import org.apache.hadoop.hbase.util.Bytes;
042import org.apache.hadoop.hbase.wal.WAL;
043import org.junit.AfterClass;
044import org.junit.BeforeClass;
045import org.junit.ClassRule;
046import org.junit.Rule;
047import org.junit.Test;
048import org.junit.experimental.categories.Category;
049import org.junit.rules.TestName;
050import org.slf4j.Logger;
051import org.slf4j.LoggerFactory;
052
053@Category(LargeTests.class)
054public class TestCheckAndMutateWithByteBuff {
055  private static final Logger LOG = LoggerFactory.getLogger(TestCheckAndMutateWithByteBuff.class);
056
057  @ClassRule
058  public static final HBaseClassTestRule CLASS_RULE =
059    HBaseClassTestRule.forClass(TestCheckAndMutateWithByteBuff.class);
060
061  @Rule
062  public TestName name = new TestName();
063
064  private static final byte[] CF = Bytes.toBytes("CF");
065  private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
066  private static final Configuration conf = TEST_UTIL.getConfiguration();
067  private static Admin admin = null;
068
069  @BeforeClass
070  public static void setupBeforeClass() throws Exception {
071    conf.set(HConstants.REGION_IMPL, TestCheckAndMutateRegion.class.getName());
072    conf.set(ByteBuffAllocator.BYTEBUFF_ALLOCATOR_CLASS,
073      DeallocateRewriteByteBuffAllocator.class.getName());
074    conf.setBoolean(ByteBuffAllocator.ALLOCATOR_POOL_ENABLED_KEY, true);
075    conf.setInt(ByteBuffAllocator.MIN_ALLOCATE_SIZE_KEY, 1);
076    conf.setInt(BlockCacheFactory.BUCKET_CACHE_WRITER_THREADS_KEY, 20);
077    conf.setInt(ByteBuffAllocator.BUFFER_SIZE_KEY, 1024);
078    conf.set(HConstants.BUCKET_CACHE_IOENGINE_KEY, "offheap");
079    conf.setInt(HConstants.BUCKET_CACHE_SIZE_KEY, 64);
080    conf.setInt("hbase.client.retries.number", 1);
081    TEST_UTIL.startMiniCluster();
082    admin = TEST_UTIL.getAdmin();
083  }
084
085  @AfterClass
086  public static void tearDownAfterClass() throws Exception {
087    TEST_UTIL.shutdownMiniCluster();
088  }
089
090  @Test
091  public void testCheckAndMutateWithByteBuffNoEncode() throws Exception {
092    testCheckAndMutateWithByteBuff(TableName.valueOf(name.getMethodName()), DataBlockEncoding.NONE);
093  }
094
095  @Test
096  public void testCheckAndMutateWithByteBuffEncode() throws Exception {
097    // Tests for HBASE-26777.
098    // As most HBase.getRegion() calls have been factored out from HBase, you'd need to revert
099    // both HBASE-26777, and the HBase.get() replacements from HBASE-26036 for this test to fail
100    testCheckAndMutateWithByteBuff(TableName.valueOf(name.getMethodName()),
101      DataBlockEncoding.FAST_DIFF);
102  }
103
104  private void testCheckAndMutateWithByteBuff(TableName tableName, DataBlockEncoding dbe)
105    throws Exception {
106    Table testTable = createTable(tableName, dbe);
107    byte[] checkRow = Bytes.toBytes("checkRow");
108    byte[] checkQualifier = Bytes.toBytes("cq");
109    byte[] checkValue = Bytes.toBytes("checkValue");
110
111    Put put = new Put(checkRow);
112    put.addColumn(CF, checkQualifier, checkValue);
113    testTable.put(put);
114    admin.flush(testTable.getName());
115
116    assertTrue(testTable.checkAndMutate(checkRow, CF).qualifier(checkQualifier).ifEquals(checkValue)
117      .thenPut(new Put(checkRow).addColumn(CF, Bytes.toBytes("q1"), Bytes.toBytes("testValue"))));
118  }
119
120  private Table createTable(TableName tableName, DataBlockEncoding dbe) throws IOException {
121    TableDescriptor td =
122      TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(ColumnFamilyDescriptorBuilder
123        .newBuilder(CF).setBlocksize(100).setDataBlockEncoding(dbe).build()).build();
124    return TEST_UTIL.createTable(td, null);
125  }
126
127  /**
128   * An override of HRegion to allow sleep after get(), waiting for the release of DBB
129   */
130  public static class TestCheckAndMutateRegion extends HRegion {
131    public TestCheckAndMutateRegion(Path tableDir, WAL log, FileSystem fs, Configuration confParam,
132      RegionInfo info, TableDescriptor htd, RegionServerServices rsServices) {
133      super(tableDir, log, fs, confParam, info, htd, rsServices);
134    }
135
136    public TestCheckAndMutateRegion(HRegionFileSystem fs, WAL wal, Configuration confParam,
137      TableDescriptor htd, RegionServerServices rsServices) {
138      super(fs, wal, confParam, htd, rsServices);
139    }
140
141    @Override
142    public List<Cell> get(Get get, boolean withCoprocessor) throws IOException {
143      List<Cell> cells = super.get(get, withCoprocessor);
144      sleep(600);
145      return cells;
146    }
147  }
148}