1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.client;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.fail;
23
24 import java.io.IOException;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Map;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.CategoryBasedTimeout;
34 import org.apache.hadoop.hbase.Cell;
35 import org.apache.hadoop.hbase.DoNotRetryIOException;
36 import org.apache.hadoop.hbase.HBaseTestingUtility;
37 import org.apache.hadoop.hbase.HConstants;
38 import org.apache.hadoop.hbase.HTableDescriptor;
39 import org.apache.hadoop.hbase.TableName;
40 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
41 import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint;
42 import org.apache.hadoop.hbase.testclassification.LargeTests;
43 import org.apache.hadoop.hbase.util.Bytes;
44 import org.junit.AfterClass;
45 import org.junit.BeforeClass;
46 import org.junit.Rule;
47 import org.junit.Test;
48 import org.junit.experimental.categories.Category;
49 import org.junit.rules.TestName;
50 import org.junit.rules.TestRule;
51
52
53
54
55
56
57
58
59
60
61 @Category(LargeTests.class)
62 @SuppressWarnings ("deprecation")
63 public class TestIncrementsFromClientSide {
64 final Log LOG = LogFactory.getLog(getClass());
65 protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
66 private static byte [] ROW = Bytes.toBytes("testRow");
67 private static byte [] FAMILY = Bytes.toBytes("testFamily");
68 private static byte [] QUALIFIER = Bytes.toBytes("testQualifier");
69
70
71 protected static int SLAVES = 1;
72 @Rule public TestName name = new TestName();
73 @Rule public final TestRule timeout = CategoryBasedTimeout.builder().withTimeout(this.getClass()).
74 withLookingForStuckThread(true).build();
75 public static Collection<Object []> data() {
76 return Arrays.asList(new Object[] {Boolean.FALSE}, new Object [] {Boolean.TRUE});
77 }
78
79 @BeforeClass
80 public static void beforeClass() throws Exception {
81 Configuration conf = TEST_UTIL.getConfiguration();
82 conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
83 MultiRowMutationEndpoint.class.getName());
84 conf.setBoolean("hbase.table.sanity.checks", true);
85
86 TEST_UTIL.startMiniCluster(SLAVES);
87 }
88
89
90
91
92 @AfterClass
93 public static void afterClass() throws Exception {
94 TEST_UTIL.shutdownMiniCluster();
95 }
96
97
98
99
100 @Test
101 public void testDuplicateIncrement() throws Exception {
102 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testDuplicateIncrement");
103 Map<String, String> kvs = new HashMap<String, String>();
104 kvs.put(HConnectionTestingUtility.SleepAtFirstRpcCall.SLEEP_TIME_CONF_KEY, "2000");
105 hdt.addCoprocessor(HConnectionTestingUtility.SleepAtFirstRpcCall.class.getName(), null, 1, kvs);
106 TEST_UTIL.createTable(hdt, new byte[][] { ROW }).close();
107
108 Configuration c = new Configuration(TEST_UTIL.getConfiguration());
109 c.setInt(HConstants.HBASE_CLIENT_PAUSE, 50);
110
111 c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500);
112
113 Connection connection = ConnectionFactory.createConnection(c);
114 Table t = connection.getTable(TableName.valueOf("HCM-testDuplicateIncrement"));
115 if (t instanceof HTable) {
116 HTable table = (HTable) t;
117 table.setOperationTimeout(3 * 1000);
118
119 try {
120 Increment inc = new Increment(ROW);
121 inc.addColumn(TEST_UTIL.fam1, QUALIFIER, 1);
122 Result result = table.increment(inc);
123
124 Cell [] cells = result.rawCells();
125 assertEquals(1, cells.length);
126 assertIncrementKey(cells[0], ROW, TEST_UTIL.fam1, QUALIFIER, 1);
127
128
129 Result readResult = table.get(new Get(ROW));
130 cells = readResult.rawCells();
131 assertEquals(1, cells.length);
132 assertIncrementKey(cells[0], ROW, TEST_UTIL.fam1, QUALIFIER, 1);
133 } finally {
134 table.close();
135 connection.close();
136 }
137 }
138 }
139
140 @Test
141 public void testIncrementWithDeletes() throws Exception {
142 LOG.info("Starting " + this.name.getMethodName());
143 final TableName TABLENAME =
144 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName()));
145 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY);
146 final byte[] COLUMN = Bytes.toBytes("column");
147
148 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5);
149 TEST_UTIL.flush(TABLENAME);
150
151 Delete del = new Delete(ROW);
152 ht.delete(del);
153
154 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5);
155
156 Get get = new Get(ROW);
157 Result r = ht.get(get);
158 assertEquals(1, r.size());
159 assertEquals(5, Bytes.toLong(r.getValue(FAMILY, COLUMN)));
160 }
161
162 @Test
163 public void testIncrementingInvalidValue() throws Exception {
164 LOG.info("Starting " + this.name.getMethodName());
165 final TableName TABLENAME =
166 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName()));
167 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY);
168 final byte[] COLUMN = Bytes.toBytes("column");
169 Put p = new Put(ROW);
170
171 p.add(FAMILY, COLUMN, Bytes.toBytes(5));
172 ht.put(p);
173 try {
174 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5);
175 fail("Should have thrown DoNotRetryIOException");
176 } catch (DoNotRetryIOException iox) {
177
178 }
179 Increment inc = new Increment(ROW);
180 inc.addColumn(FAMILY, COLUMN, 5);
181 try {
182 ht.increment(inc);
183 fail("Should have thrown DoNotRetryIOException");
184 } catch (DoNotRetryIOException iox) {
185
186 }
187 }
188
189 @Test
190 public void testIncrementInvalidArguments() throws Exception {
191 LOG.info("Starting " + this.name.getMethodName());
192 final TableName TABLENAME =
193 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName()));
194 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY);
195 final byte[] COLUMN = Bytes.toBytes("column");
196 try {
197
198 ht.incrementColumnValue(null, FAMILY, COLUMN, 5);
199 fail("Should have thrown IOException");
200 } catch (IOException iox) {
201
202 }
203 try {
204
205 ht.incrementColumnValue(ROW, null, COLUMN, 5);
206 fail("Should have thrown IOException");
207 } catch (IOException iox) {
208
209 }
210 try {
211
212 ht.incrementColumnValue(ROW, FAMILY, null, 5);
213 fail("Should have thrown IOException");
214 } catch (IOException iox) {
215
216 }
217
218 try {
219 Increment incNoRow = new Increment((byte [])null);
220 incNoRow.addColumn(FAMILY, COLUMN, 5);
221 fail("Should have thrown IllegalArgumentException");
222 } catch (IllegalArgumentException iax) {
223
224 } catch (NullPointerException npe) {
225
226 }
227
228 try {
229 Increment incNoFamily = new Increment(ROW);
230 incNoFamily.addColumn(null, COLUMN, 5);
231 fail("Should have thrown IllegalArgumentException");
232 } catch (IllegalArgumentException iax) {
233
234 }
235
236 try {
237 Increment incNoQualifier = new Increment(ROW);
238 incNoQualifier.addColumn(FAMILY, null, 5);
239 fail("Should have thrown IllegalArgumentException");
240 } catch (IllegalArgumentException iax) {
241
242 }
243 }
244
245 @Test
246 public void testIncrementOutOfOrder() throws Exception {
247 LOG.info("Starting " + this.name.getMethodName());
248 final TableName TABLENAME =
249 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName()));
250 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY);
251
252 byte [][] QUALIFIERS = new byte [][] {
253 Bytes.toBytes("B"), Bytes.toBytes("A"), Bytes.toBytes("C")
254 };
255
256 Increment inc = new Increment(ROW);
257 for (int i=0; i<QUALIFIERS.length; i++) {
258 inc.addColumn(FAMILY, QUALIFIERS[i], 1);
259 }
260 ht.increment(inc);
261
262
263 Get get = new Get(ROW);
264 Result r = ht.get(get);
265 Cell [] kvs = r.rawCells();
266 assertEquals(3, kvs.length);
267 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[1], 1);
268 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[0], 1);
269 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 1);
270
271
272 inc = new Increment(ROW);
273 for (int i=0; i<QUALIFIERS.length; i++) {
274 inc.addColumn(FAMILY, QUALIFIERS[i], 1);
275 }
276 ht.increment(inc);
277
278
279 r = ht.get(get);
280 kvs = r.rawCells();
281 assertEquals(3, kvs.length);
282 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[1], 2);
283 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[0], 2);
284 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 2);
285 }
286
287 @Test
288 public void testIncrementOnSameColumn() throws Exception {
289 LOG.info("Starting " + this.name.getMethodName());
290 final byte[] TABLENAME = Bytes.toBytes(filterStringSoTableNameSafe(this.name.getMethodName()));
291 HTable ht = TEST_UTIL.createTable(TABLENAME, FAMILY);
292
293 byte[][] QUALIFIERS =
294 new byte[][] { Bytes.toBytes("A"), Bytes.toBytes("B"), Bytes.toBytes("C") };
295
296 Increment inc = new Increment(ROW);
297 for (int i = 0; i < QUALIFIERS.length; i++) {
298 inc.addColumn(FAMILY, QUALIFIERS[i], 1);
299 inc.addColumn(FAMILY, QUALIFIERS[i], 1);
300 }
301 ht.increment(inc);
302
303
304 Get get = new Get(ROW);
305 Result r = ht.get(get);
306 Cell[] kvs = r.rawCells();
307 assertEquals(3, kvs.length);
308 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 1);
309 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 1);
310 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 1);
311
312
313 inc = new Increment(ROW);
314 for (int i = 0; i < QUALIFIERS.length; i++) {
315 inc.addColumn(FAMILY, QUALIFIERS[i], 1);
316 inc.addColumn(FAMILY, QUALIFIERS[i], 1);
317 }
318 ht.increment(inc);
319
320
321 r = ht.get(get);
322 kvs = r.rawCells();
323 assertEquals(3, kvs.length);
324 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 2);
325 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 2);
326 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 2);
327
328 ht.close();
329 }
330
331 @Test
332 public void testIncrement() throws Exception {
333 LOG.info("Starting " + this.name.getMethodName());
334 final TableName TABLENAME =
335 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName()));
336 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY);
337
338 byte [][] ROWS = new byte [][] {
339 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c"),
340 Bytes.toBytes("d"), Bytes.toBytes("e"), Bytes.toBytes("f"),
341 Bytes.toBytes("g"), Bytes.toBytes("h"), Bytes.toBytes("i")
342 };
343 byte [][] QUALIFIERS = new byte [][] {
344 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c"),
345 Bytes.toBytes("d"), Bytes.toBytes("e"), Bytes.toBytes("f"),
346 Bytes.toBytes("g"), Bytes.toBytes("h"), Bytes.toBytes("i")
347 };
348
349
350
351
352 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[0], 1);
353 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[1], 2);
354 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[2], 3);
355 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[3], 4);
356
357
358 Increment inc = new Increment(ROW);
359 inc.addColumn(FAMILY, QUALIFIERS[1], 1);
360 inc.addColumn(FAMILY, QUALIFIERS[3], 1);
361 inc.addColumn(FAMILY, QUALIFIERS[4], 1);
362 ht.increment(inc);
363
364
365 Get get = new Get(ROW);
366 Result r = ht.get(get);
367 Cell [] kvs = r.rawCells();
368 assertEquals(5, kvs.length);
369 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 1);
370 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 3);
371 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 3);
372 assertIncrementKey(kvs[3], ROW, FAMILY, QUALIFIERS[3], 5);
373 assertIncrementKey(kvs[4], ROW, FAMILY, QUALIFIERS[4], 1);
374
375
376 inc = new Increment(ROWS[0]);
377 for (int i=0;i<QUALIFIERS.length;i++) {
378 inc.addColumn(FAMILY, QUALIFIERS[i], i+1);
379 }
380 ht.increment(inc);
381
382 get = new Get(ROWS[0]);
383 r = ht.get(get);
384 kvs = r.rawCells();
385 assertEquals(QUALIFIERS.length, kvs.length);
386 for (int i=0;i<QUALIFIERS.length;i++) {
387 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], i+1);
388 }
389
390
391 inc = new Increment(ROWS[0]);
392 for (int i=0;i<QUALIFIERS.length;i++) {
393 inc.addColumn(FAMILY, QUALIFIERS[i], i+1);
394 }
395 ht.increment(inc);
396
397 r = ht.get(get);
398 kvs = r.rawCells();
399 assertEquals(QUALIFIERS.length, kvs.length);
400 for (int i=0;i<QUALIFIERS.length;i++) {
401 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], 2*(i+1));
402 }
403
404
405
406 inc = new Increment(ROWS[0]);
407 for (int i = 0; i < QUALIFIERS.length; i++) {
408 inc.addColumn(FAMILY, QUALIFIERS[i], 0);
409 }
410 ht.increment(inc);
411 r = ht.get(get);
412 kvs = r.rawCells();
413 assertEquals(QUALIFIERS.length, kvs.length);
414 for (int i = 0; i < QUALIFIERS.length; i++) {
415 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], 2*(i+1));
416 }
417 }
418
419
420
421
422
423 static void assertIncrementKey(Cell key, byte [] row, byte [] family,
424 byte [] qualifier, long value) throws Exception {
425 TestFromClientSide.assertIncrementKey(key, row, family, qualifier, value);
426 }
427
428 public static String filterStringSoTableNameSafe(final String str) {
429 return str.replaceAll("\\[fast\\=(.*)\\]", ".FAST.is.$1");
430 }
431 }