View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.coprocessor;
21  
22  import static org.junit.Assert.assertArrayEquals;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.io.IOException;
27  import java.util.Arrays;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.NavigableMap;
31  
32  import org.apache.hadoop.hbase.Cell;
33  import org.apache.hadoop.hbase.HBaseTestingUtility;
34  import org.apache.hadoop.hbase.TableName;
35  import org.apache.hadoop.hbase.client.Durability;
36  import org.apache.hadoop.hbase.client.Get;
37  import org.apache.hadoop.hbase.client.Increment;
38  import org.apache.hadoop.hbase.client.Put;
39  import org.apache.hadoop.hbase.client.Result;
40  import org.apache.hadoop.hbase.client.Row;
41  import org.apache.hadoop.hbase.client.Table;
42  import org.apache.hadoop.hbase.io.TimeRange;
43  import org.apache.hadoop.hbase.testclassification.CoprocessorTests;
44  import org.apache.hadoop.hbase.testclassification.MediumTests;
45  import org.apache.hadoop.hbase.util.Bytes;
46  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
47  import org.apache.hadoop.hbase.util.ManualEnvironmentEdge;
48  import org.junit.After;
49  import org.junit.AfterClass;
50  import org.junit.Before;
51  import org.junit.BeforeClass;
52  import org.junit.Test;
53  import org.junit.experimental.categories.Category;
54  
55  /**
56   * This test runs batch mutation with Increments which have custom TimeRange.
57   * Custom Observer records the TimeRange.
58   * We then verify that the recorded TimeRange has same bounds as the initial TimeRange.
59   * See HBASE-15698
60   */
61  @Category({CoprocessorTests.class, MediumTests.class})
62  public class TestIncrementTimeRange {
63  
64    private static final HBaseTestingUtility util = new HBaseTestingUtility();
65    private static ManualEnvironmentEdge mee = new ManualEnvironmentEdge();
66  
67    private static final TableName TEST_TABLE = TableName.valueOf("test");
68    private static final byte[] TEST_FAMILY = Bytes.toBytes("f1");
69  
70    private static final byte[] ROW_A = Bytes.toBytes("aaa");
71    private static final byte[] ROW_B = Bytes.toBytes("bbb");
72    private static final byte[] ROW_C = Bytes.toBytes("ccc");
73  
74    private static final byte[] qualifierCol1 = Bytes.toBytes("col1");
75  
76    private static final byte[] bytes1 = Bytes.toBytes(1);
77    private static final byte[] bytes2 = Bytes.toBytes(2);
78    private static final byte[] bytes3 = Bytes.toBytes(3);
79  
80    private Table hTableInterface;
81    private Table table;
82  
83    @BeforeClass
84    public static void setupBeforeClass() throws Exception {
85      util.getConfiguration().set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
86          MyObserver.class.getName());
87      util.startMiniCluster();
88      EnvironmentEdgeManager.injectEdge(mee);
89    }
90  
91    @AfterClass
92    public static void tearDownAfterClass() throws Exception {
93      util.shutdownMiniCluster();
94    }
95  
96    @Before
97    public void before() throws Exception {
98      table = util.createTable(TEST_TABLE, TEST_FAMILY);
99  
100     Put puta = new Put(ROW_A);
101     puta.addColumn(TEST_FAMILY, qualifierCol1, bytes1);
102     table.put(puta);
103 
104     Put putb = new Put(ROW_B);
105     putb.addColumn(TEST_FAMILY, qualifierCol1, bytes2);
106     table.put(putb);
107 
108     Put putc = new Put(ROW_C);
109     putc.addColumn(TEST_FAMILY, qualifierCol1, bytes3);
110     table.put(putc);
111   }
112 
113   @After
114   public void after() throws Exception {
115     try {
116       if (table != null) {
117         table.close();
118       }
119     } finally {
120       try {
121         util.deleteTable(TEST_TABLE);
122       } catch (IOException ioe) {
123       }
124     }
125   }
126 
127   public static class MyObserver extends SimpleRegionObserver {
128     static TimeRange tr10 = null, tr2 = null;
129     @Override
130     public Result preIncrement(final ObserverContext<RegionCoprocessorEnvironment> e,
131         final Increment increment) throws IOException {
132       NavigableMap<byte [], List<Cell>> map = increment.getFamilyCellMap();
133       for (Map.Entry<byte [], List<Cell>> entry : map.entrySet()) {
134         for (Cell cell : entry.getValue()) {
135           long incr = Bytes.toLong(cell.getValueArray(), cell.getValueOffset(),
136               cell.getValueLength());
137           if (incr == 10) {
138             tr10 = increment.getTimeRange();
139           } else if (incr == 2 && !increment.getTimeRange().isAllTime()) {
140             tr2 = increment.getTimeRange();
141           }
142         }
143       }
144       return super.preIncrement(e, increment);
145     }
146   }
147 
148   @Test
149   public void testHTableInterfaceMethods() throws Exception {
150     hTableInterface = util.getConnection().getTable(TEST_TABLE);
151     checkHTableInterfaceMethods();
152   }
153 
154   private void checkHTableInterfaceMethods() throws Exception {
155     long time = EnvironmentEdgeManager.currentTime();
156     mee.setValue(time);
157     hTableInterface.put(new Put(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, Bytes.toBytes(1L)));
158     checkRowValue(ROW_A, Bytes.toBytes(1L));
159 
160     time = EnvironmentEdgeManager.currentTime();
161     mee.setValue(time);
162     TimeRange range10 = new TimeRange(1, time+10);
163     hTableInterface.increment(new Increment(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, 10L)
164         .setTimeRange(range10.getMin(), range10.getMax()));
165     checkRowValue(ROW_A, Bytes.toBytes(11L));
166     assertEquals(MyObserver.tr10.getMin(), range10.getMin());
167     assertEquals(MyObserver.tr10.getMax(), range10.getMax());
168 
169     time = EnvironmentEdgeManager.currentTime();
170     mee.setValue(time);
171     TimeRange range2 = new TimeRange(1, time+20);
172     List<Row> actions =
173         Arrays.asList(new Row[] { new Increment(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, 2L)
174             .setTimeRange(range2.getMin(), range2.getMax()),
175             new Increment(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, 2L)
176             .setTimeRange(range2.getMin(), range2.getMax()) });
177     Object[] results3 = new Object[actions.size()];
178     Object[] results1 = results3;
179     hTableInterface.batch(actions, results1);
180     assertEquals(MyObserver.tr2.getMin(), range2.getMin());
181     assertEquals(MyObserver.tr2.getMax(), range2.getMax());
182     for (Object r2 : results1) {
183       assertTrue(r2 instanceof Result);
184     }
185     checkRowValue(ROW_A, Bytes.toBytes(15L));
186 
187     hTableInterface.close();
188   }
189 
190   private void checkRowValue(byte[] row, byte[] expectedValue) throws IOException {
191     Get get = new Get(row).addColumn(TEST_FAMILY, qualifierCol1);
192     Result result = hTableInterface.get(get);
193     byte[] actualValue = result.getValue(TEST_FAMILY, qualifierCol1);
194     assertArrayEquals(expectedValue, actualValue);
195   }
196 }