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