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