1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.coprocessor;
21
22 import static org.junit.Assert.assertArrayEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertTrue;
26
27 import java.io.IOException;
28 import java.lang.reflect.Method;
29 import java.util.ArrayList;
30 import java.util.List;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.fs.FileSystem;
36 import org.apache.hadoop.fs.Path;
37 import org.apache.hadoop.hbase.Cell;
38 import org.apache.hadoop.hbase.CellUtil;
39 import org.apache.hadoop.hbase.Coprocessor;
40 import org.apache.hadoop.hbase.HBaseTestingUtility;
41 import org.apache.hadoop.hbase.HColumnDescriptor;
42 import org.apache.hadoop.hbase.HRegionInfo;
43 import org.apache.hadoop.hbase.HTableDescriptor;
44 import org.apache.hadoop.hbase.KeyValue;
45 import org.apache.hadoop.hbase.testclassification.MediumTests;
46 import org.apache.hadoop.hbase.MiniHBaseCluster;
47 import org.apache.hadoop.hbase.ServerName;
48 import org.apache.hadoop.hbase.TableName;
49 import org.apache.hadoop.hbase.client.Append;
50 import org.apache.hadoop.hbase.client.Delete;
51 import org.apache.hadoop.hbase.client.Durability;
52 import org.apache.hadoop.hbase.client.Get;
53 import org.apache.hadoop.hbase.client.HBaseAdmin;
54 import org.apache.hadoop.hbase.client.HTable;
55 import org.apache.hadoop.hbase.client.Increment;
56 import org.apache.hadoop.hbase.client.Put;
57 import org.apache.hadoop.hbase.client.Result;
58 import org.apache.hadoop.hbase.client.ResultScanner;
59 import org.apache.hadoop.hbase.client.RowMutations;
60 import org.apache.hadoop.hbase.client.Scan;
61 import org.apache.hadoop.hbase.filter.FilterAllFilter;
62 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
63 import org.apache.hadoop.hbase.io.hfile.HFile;
64 import org.apache.hadoop.hbase.io.hfile.HFileContext;
65 import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;
66 import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
67 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
68 import org.apache.hadoop.hbase.regionserver.HRegion;
69 import org.apache.hadoop.hbase.regionserver.InternalScanner;
70 import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
71 import org.apache.hadoop.hbase.regionserver.ScanType;
72 import org.apache.hadoop.hbase.regionserver.Store;
73 import org.apache.hadoop.hbase.regionserver.StoreFile;
74 import org.apache.hadoop.hbase.util.Bytes;
75 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
76 import org.apache.hadoop.hbase.util.JVMClusterUtil;
77 import org.apache.hadoop.hbase.util.Threads;
78 import org.junit.AfterClass;
79 import org.junit.BeforeClass;
80 import org.junit.Test;
81 import org.junit.experimental.categories.Category;
82
83 @Category(MediumTests.class)
84 public class TestRegionObserverInterface {
85 static final Log LOG = LogFactory.getLog(TestRegionObserverInterface.class);
86
87 public static final TableName TEST_TABLE = TableName.valueOf("TestTable");
88 public final static byte[] A = Bytes.toBytes("a");
89 public final static byte[] B = Bytes.toBytes("b");
90 public final static byte[] C = Bytes.toBytes("c");
91 public final static byte[] ROW = Bytes.toBytes("testrow");
92
93 private static HBaseTestingUtility util = new HBaseTestingUtility();
94 private static MiniHBaseCluster cluster = null;
95
96 @BeforeClass
97 public static void setupBeforeClass() throws Exception {
98
99 Configuration conf = util.getConfiguration();
100 conf.setBoolean("hbase.master.distributed.log.replay", true);
101 conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
102 "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver");
103
104 util.startMiniCluster();
105 cluster = util.getMiniHBaseCluster();
106 }
107
108 @AfterClass
109 public static void tearDownAfterClass() throws Exception {
110 util.shutdownMiniCluster();
111 }
112
113 @Test
114 public void testRegionObserver() throws IOException {
115 TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testRegionObserver");
116
117
118 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
119 try {
120 verifyMethodResult(SimpleRegionObserver.class, new String[] { "hadPreGet", "hadPostGet",
121 "hadPrePut", "hadPostPut", "hadDelete", "hadPostStartRegionOperation",
122 "hadPostCloseRegionOperation", "hadPostBatchMutateIndispensably" }, tableName,
123 new Boolean[] { false, false, false, false, false, false, false, false });
124
125 Put put = new Put(ROW);
126 put.add(A, A, A);
127 put.add(B, B, B);
128 put.add(C, C, C);
129 table.put(put);
130
131 verifyMethodResult(SimpleRegionObserver.class, new String[] { "hadPreGet", "hadPostGet",
132 "hadPrePut", "hadPostPut", "hadPreBatchMutate", "hadPostBatchMutate", "hadDelete",
133 "hadPostStartRegionOperation", "hadPostCloseRegionOperation",
134 "hadPostBatchMutateIndispensably" }, TEST_TABLE, new Boolean[] { false, false, true,
135 true, true, true, false, true, true, true });
136
137 verifyMethodResult(SimpleRegionObserver.class,
138 new String[] {"getCtPreOpen", "getCtPostOpen", "getCtPreClose", "getCtPostClose"},
139 tableName,
140 new Integer[] {1, 1, 0, 0});
141
142 Get get = new Get(ROW);
143 get.addColumn(A, A);
144 get.addColumn(B, B);
145 get.addColumn(C, C);
146 table.get(get);
147
148 verifyMethodResult(SimpleRegionObserver.class,
149 new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
150 "hadDelete", "hadPrePreparedDeleteTS"},
151 tableName,
152 new Boolean[] {true, true, true, true, false, false}
153 );
154
155 Delete delete = new Delete(ROW);
156 delete.deleteColumn(A, A);
157 delete.deleteColumn(B, B);
158 delete.deleteColumn(C, C);
159 table.delete(delete);
160
161 verifyMethodResult(SimpleRegionObserver.class,
162 new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
163 "hadPreBatchMutate", "hadPostBatchMutate", "hadDelete", "hadPrePreparedDeleteTS"},
164 tableName,
165 new Boolean[] {true, true, true, true, true, true, true, true}
166 );
167 } finally {
168 util.deleteTable(tableName);
169 table.close();
170 }
171 verifyMethodResult(SimpleRegionObserver.class,
172 new String[] {"getCtPreOpen", "getCtPostOpen", "getCtPreClose", "getCtPostClose"},
173 tableName,
174 new Integer[] {1, 1, 1, 1});
175 }
176
177 @Test
178 public void testRowMutation() throws IOException {
179 TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testRowMutation");
180 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
181 try {
182 verifyMethodResult(SimpleRegionObserver.class,
183 new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
184 "hadDeleted"},
185 tableName,
186 new Boolean[] {false, false, false, false, false});
187 Put put = new Put(ROW);
188 put.add(A, A, A);
189 put.add(B, B, B);
190 put.add(C, C, C);
191
192 Delete delete = new Delete(ROW);
193 delete.deleteColumn(A, A);
194 delete.deleteColumn(B, B);
195 delete.deleteColumn(C, C);
196
197 RowMutations arm = new RowMutations(ROW);
198 arm.add(put);
199 arm.add(delete);
200 table.mutateRow(arm);
201
202 verifyMethodResult(SimpleRegionObserver.class,
203 new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
204 "hadDeleted"},
205 tableName,
206 new Boolean[] {false, false, true, true, true}
207 );
208 } finally {
209 util.deleteTable(tableName);
210 table.close();
211 }
212 }
213
214 @Test
215 public void testIncrementHook() throws IOException {
216 TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testIncrementHook");
217 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
218 try {
219 Increment inc = new Increment(Bytes.toBytes(0));
220 inc.addColumn(A, A, 1);
221
222 verifyMethodResult(SimpleRegionObserver.class,
223 new String[] {"hadPreIncrement", "hadPostIncrement", "hadPreIncrementAfterRowLock"},
224 tableName,
225 new Boolean[] {false, false, false}
226 );
227
228 table.increment(inc);
229
230 verifyMethodResult(SimpleRegionObserver.class,
231 new String[] {"hadPreIncrement", "hadPostIncrement", "hadPreIncrementAfterRowLock"},
232 tableName,
233 new Boolean[] {true, true, true}
234 );
235 } finally {
236 util.deleteTable(tableName);
237 table.close();
238 }
239 }
240
241 @Test
242 public void testCheckAndPutHooks() throws IOException {
243 TableName tableName =
244 TableName.valueOf(TEST_TABLE.getNameAsString() + ".testCheckAndPutHooks");
245 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
246 try {
247 Put p = new Put(Bytes.toBytes(0));
248 p.add(A, A, A);
249 table.put(p);
250 table.flushCommits();
251 p = new Put(Bytes.toBytes(0));
252 p.add(A, A, A);
253 verifyMethodResult(SimpleRegionObserver.class,
254 new String[] {"hadPreCheckAndPut",
255 "hadPreCheckAndPutAfterRowLock", "hadPostCheckAndPut"},
256 tableName,
257 new Boolean[] {false, false, false}
258 );
259 table.checkAndPut(Bytes.toBytes(0), A, A, A, p);
260 verifyMethodResult(SimpleRegionObserver.class,
261 new String[] {"hadPreCheckAndPut",
262 "hadPreCheckAndPutAfterRowLock", "hadPostCheckAndPut"},
263 tableName,
264 new Boolean[] {true, true, true}
265 );
266 } finally {
267 util.deleteTable(tableName);
268 table.close();
269 }
270 }
271
272 @Test
273 public void testCheckAndDeleteHooks() throws IOException {
274 TableName tableName =
275 TableName.valueOf(TEST_TABLE.getNameAsString() + ".testCheckAndDeleteHooks");
276 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
277 try {
278 Put p = new Put(Bytes.toBytes(0));
279 p.add(A, A, A);
280 table.put(p);
281 table.flushCommits();
282 Delete d = new Delete(Bytes.toBytes(0));
283 table.delete(d);
284 verifyMethodResult(SimpleRegionObserver.class,
285 new String[] {"hadPreCheckAndDelete",
286 "hadPreCheckAndDeleteAfterRowLock", "hadPostCheckAndDelete"},
287 tableName,
288 new Boolean[] {false, false, false}
289 );
290 table.checkAndDelete(Bytes.toBytes(0), A, A, A, d);
291 verifyMethodResult(SimpleRegionObserver.class,
292 new String[] {"hadPreCheckAndDelete",
293 "hadPreCheckAndDeleteAfterRowLock", "hadPostCheckAndDelete"},
294 tableName,
295 new Boolean[] {true, true, true}
296 );
297 } finally {
298 util.deleteTable(tableName);
299 table.close();
300 }
301 }
302
303 @Test
304 public void testAppendHook() throws IOException {
305 TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testAppendHook");
306 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
307 try {
308 Append app = new Append(Bytes.toBytes(0));
309 app.add(A, A, A);
310
311 verifyMethodResult(SimpleRegionObserver.class,
312 new String[] {"hadPreAppend", "hadPostAppend", "hadPreAppendAfterRowLock"},
313 tableName,
314 new Boolean[] {false, false, false}
315 );
316
317 table.append(app);
318
319 verifyMethodResult(SimpleRegionObserver.class,
320 new String[] {"hadPreAppend", "hadPostAppend", "hadPreAppendAfterRowLock"},
321 tableName,
322 new Boolean[] {true, true, true}
323 );
324 } finally {
325 util.deleteTable(tableName);
326 table.close();
327 }
328 }
329
330 @Test
331
332 public void testHBase3583() throws IOException {
333 TableName tableName =
334 TableName.valueOf("testHBase3583");
335 util.createTable(tableName, new byte[][] {A, B, C});
336 util.waitUntilAllRegionsAssigned(tableName);
337
338 verifyMethodResult(SimpleRegionObserver.class,
339 new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled",
340 "wasScannerCloseCalled"},
341 tableName,
342 new Boolean[] {false, false, false, false}
343 );
344
345 HTable table = new HTable(util.getConfiguration(), tableName);
346 Put put = new Put(ROW);
347 put.add(A, A, A);
348 table.put(put);
349
350 Get get = new Get(ROW);
351 get.addColumn(A, A);
352 table.get(get);
353
354
355
356 verifyMethodResult(SimpleRegionObserver.class,
357 new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled",
358 "wasScannerCloseCalled"},
359 tableName,
360 new Boolean[] {true, true, false, false}
361 );
362
363 Scan s = new Scan();
364 ResultScanner scanner = table.getScanner(s);
365 try {
366 for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
367 }
368 } finally {
369 scanner.close();
370 }
371
372
373 verifyMethodResult(SimpleRegionObserver.class,
374 new String[] {"wasScannerNextCalled", "wasScannerCloseCalled"},
375 tableName,
376 new Boolean[] {true, true}
377 );
378 util.deleteTable(tableName);
379 table.close();
380 }
381
382 @Test
383 public void testHBASE14489() throws IOException {
384 TableName tableName =
385 TableName.valueOf("testHBASE14489");
386 HTable table = util.createTable(tableName, new byte[][] {A});
387 Put put = new Put(ROW);
388 put.add(A, A, A);
389 table.put(put);
390
391 Scan s = new Scan();
392 s.setFilter(new FilterAllFilter());
393 ResultScanner scanner = table.getScanner(s);
394 try {
395 for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
396 }
397 } finally {
398 scanner.close();
399 }
400 verifyMethodResult(SimpleRegionObserver.class,
401 new String[] {"wasScannerFilterRowCalled"},
402 tableName,
403 new Boolean[] {true}
404 );
405 util.deleteTable(tableName);
406 table.close();
407
408 }
409
410 @Test
411
412 public void testHBase3758() throws IOException {
413 TableName tableName =
414 TableName.valueOf("testHBase3758");
415 util.createTable(tableName, new byte[][] {A, B, C});
416
417 verifyMethodResult(SimpleRegionObserver.class,
418 new String[] {"hadDeleted", "wasScannerOpenCalled"},
419 tableName,
420 new Boolean[] {false, false}
421 );
422
423 HTable table = new HTable(util.getConfiguration(), tableName);
424 Put put = new Put(ROW);
425 put.add(A, A, A);
426 table.put(put);
427
428 Delete delete = new Delete(ROW);
429 table.delete(delete);
430
431 verifyMethodResult(SimpleRegionObserver.class,
432 new String[] {"hadDeleted", "wasScannerOpenCalled"},
433 tableName,
434 new Boolean[] {true, false}
435 );
436
437 Scan s = new Scan();
438 ResultScanner scanner = table.getScanner(s);
439 try {
440 for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
441 }
442 } finally {
443 scanner.close();
444 }
445
446
447 verifyMethodResult(SimpleRegionObserver.class,
448 new String[] {"wasScannerOpenCalled"},
449 tableName,
450 new Boolean[] {true}
451 );
452 util.deleteTable(tableName);
453 table.close();
454 }
455
456
457 public static class EvenOnlyCompactor extends BaseRegionObserver {
458 long lastCompaction;
459 long lastFlush;
460
461 @Override
462 public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> e,
463 Store store, final InternalScanner scanner, final ScanType scanType) {
464 return new InternalScanner() {
465 @Override
466 public boolean next(List<Cell> results) throws IOException {
467 return next(results, -1);
468 }
469
470 @Override
471 public boolean next(List<Cell> results, int limit)
472 throws IOException{
473 List<Cell> internalResults = new ArrayList<Cell>();
474 boolean hasMore;
475 do {
476 hasMore = scanner.next(internalResults, limit);
477 if (!internalResults.isEmpty()) {
478 long row = Bytes.toLong(CellUtil.cloneValue(internalResults.get(0)));
479 if (row % 2 == 0) {
480
481 break;
482 }
483
484 internalResults.clear();
485 }
486 } while (hasMore);
487
488 if (!internalResults.isEmpty()) {
489 results.addAll(internalResults);
490 }
491 return hasMore;
492 }
493
494 @Override
495 public void close() throws IOException {
496 scanner.close();
497 }
498 };
499 }
500
501 @Override
502 public void postCompact(ObserverContext<RegionCoprocessorEnvironment> e,
503 Store store, StoreFile resultFile) {
504 lastCompaction = EnvironmentEdgeManager.currentTimeMillis();
505 }
506
507 @Override
508 public void postFlush(ObserverContext<RegionCoprocessorEnvironment> e) {
509 lastFlush = EnvironmentEdgeManager.currentTimeMillis();
510 }
511 }
512
513
514
515
516 @Test
517 public void testCompactionOverride() throws Exception {
518 byte[] compactTable = Bytes.toBytes("TestCompactionOverride");
519 HBaseAdmin admin = util.getHBaseAdmin();
520 if (admin.tableExists(compactTable)) {
521 admin.disableTable(compactTable);
522 admin.deleteTable(compactTable);
523 }
524
525 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(compactTable));
526 htd.addFamily(new HColumnDescriptor(A));
527 htd.addCoprocessor(EvenOnlyCompactor.class.getName());
528 admin.createTable(htd);
529
530 HTable table = new HTable(util.getConfiguration(), compactTable);
531 for (long i=1; i<=10; i++) {
532 byte[] iBytes = Bytes.toBytes(i);
533 Put put = new Put(iBytes);
534 put.setDurability(Durability.SKIP_WAL);
535 put.add(A, A, iBytes);
536 table.put(put);
537 }
538
539 HRegion firstRegion = cluster.getRegions(compactTable).get(0);
540 Coprocessor cp = firstRegion.getCoprocessorHost().findCoprocessor(
541 EvenOnlyCompactor.class.getName());
542 assertNotNull("EvenOnlyCompactor coprocessor should be loaded", cp);
543 EvenOnlyCompactor compactor = (EvenOnlyCompactor)cp;
544
545
546 long ts = System.currentTimeMillis();
547 admin.flush(compactTable);
548
549 for (int i=0; i<10; i++) {
550 if (compactor.lastFlush >= ts) {
551 break;
552 }
553 Thread.sleep(1000);
554 }
555 assertTrue("Flush didn't complete", compactor.lastFlush >= ts);
556 LOG.debug("Flush complete");
557
558 ts = compactor.lastFlush;
559 admin.majorCompact(compactTable);
560
561 for (int i=0; i<30; i++) {
562 if (compactor.lastCompaction >= ts) {
563 break;
564 }
565 Thread.sleep(1000);
566 }
567 LOG.debug("Last compaction was at "+compactor.lastCompaction);
568 assertTrue("Compaction didn't complete", compactor.lastCompaction >= ts);
569
570
571 ResultScanner scanner = table.getScanner(new Scan());
572 try {
573 for (long i=2; i<=10; i+=2) {
574 Result r = scanner.next();
575 assertNotNull(r);
576 assertFalse(r.isEmpty());
577 byte[] iBytes = Bytes.toBytes(i);
578 assertArrayEquals("Row should be "+i, r.getRow(), iBytes);
579 assertArrayEquals("Value should be "+i, r.getValue(A, A), iBytes);
580 }
581 } finally {
582 scanner.close();
583 }
584 table.close();
585 }
586
587 @Test
588 public void bulkLoadHFileTest() throws Exception {
589 String testName = TestRegionObserverInterface.class.getName()+".bulkLoadHFileTest";
590 TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".bulkLoadHFileTest");
591 Configuration conf = util.getConfiguration();
592 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
593 try {
594 verifyMethodResult(SimpleRegionObserver.class,
595 new String[] {"hadPreBulkLoadHFile", "hadPostBulkLoadHFile"},
596 tableName,
597 new Boolean[] {false, false}
598 );
599
600 FileSystem fs = util.getTestFileSystem();
601 final Path dir = util.getDataTestDirOnTestFS(testName).makeQualified(fs);
602 Path familyDir = new Path(dir, Bytes.toString(A));
603
604 createHFile(util.getConfiguration(), fs, new Path(familyDir,Bytes.toString(A)), A, A);
605
606
607 new LoadIncrementalHFiles(conf).doBulkLoad(dir, new HTable(conf, tableName));
608
609 verifyMethodResult(SimpleRegionObserver.class,
610 new String[] {"hadPreBulkLoadHFile", "hadPostBulkLoadHFile"},
611 tableName,
612 new Boolean[] {true, true}
613 );
614 } finally {
615 util.deleteTable(tableName);
616 table.close();
617 }
618 }
619
620 @Test
621 public void testRecovery() throws Exception {
622 LOG.info(TestRegionObserverInterface.class.getName() +".testRecovery");
623 TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testRecovery");
624 HTable table = util.createTable(tableName, new byte[][] {A, B, C});
625 try {
626 JVMClusterUtil.RegionServerThread rs1 = cluster.startRegionServer();
627 ServerName sn2 = rs1.getRegionServer().getServerName();
628 String regEN = table.getRegionLocations().firstEntry().getKey().getEncodedName();
629
630 util.getHBaseAdmin().move(regEN.getBytes(), sn2.getServerName().getBytes());
631 while (!sn2.equals(table.getRegionLocations().firstEntry().getValue() )){
632 Thread.sleep(100);
633 }
634
635 Put put = new Put(ROW);
636 put.add(A, A, A);
637 put.add(B, B, B);
638 put.add(C, C, C);
639 table.put(put);
640
641 verifyMethodResult(SimpleRegionObserver.class,
642 new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
643 "hadPreBatchMutate", "hadPostBatchMutate", "hadDelete"},
644 tableName,
645 new Boolean[] {false, false, true, true, true, true, false}
646 );
647
648 verifyMethodResult(SimpleRegionObserver.class,
649 new String[] {"getCtPreWALRestore", "getCtPostWALRestore", "getCtPrePut", "getCtPostPut"},
650 tableName,
651 new Integer[] {0, 0, 1, 1});
652
653 cluster.killRegionServer(rs1.getRegionServer().getServerName());
654 Threads.sleep(1000);
655 util.waitUntilAllRegionsAssigned(tableName);
656 LOG.info("All regions assigned");
657
658 verifyMethodResult(SimpleRegionObserver.class,
659 new String[]{"getCtPrePut", "getCtPostPut"},
660 tableName,
661 new Integer[]{0, 0});
662 } finally {
663 util.deleteTable(tableName);
664 table.close();
665 }
666 }
667
668 @Test
669 public void testPreWALRestoreSkip() throws Exception {
670 LOG.info(TestRegionObserverInterface.class.getName() + ".testPreWALRestoreSkip");
671 TableName tableName = TableName.valueOf(SimpleRegionObserver.TABLE_SKIPPED);
672 HTable table = util.createTable(tableName, new byte[][] { A, B, C });
673
674 JVMClusterUtil.RegionServerThread rs1 = cluster.startRegionServer();
675 ServerName sn2 = rs1.getRegionServer().getServerName();
676 String regEN = table.getRegionLocations().firstEntry().getKey().getEncodedName();
677
678 util.getHBaseAdmin().move(regEN.getBytes(), sn2.getServerName().getBytes());
679 while (!sn2.equals(table.getRegionLocations().firstEntry().getValue())) {
680 Thread.sleep(100);
681 }
682
683 Put put = new Put(ROW);
684 put.add(A, A, A);
685 put.add(B, B, B);
686 put.add(C, C, C);
687 table.put(put);
688 table.flushCommits();
689
690 cluster.killRegionServer(rs1.getRegionServer().getServerName());
691 Threads.sleep(20000);
692 util.waitUntilAllRegionsAssigned(tableName);
693
694 verifyMethodResult(SimpleRegionObserver.class, new String[] { "getCtPreWALRestore",
695 "getCtPostWALRestore" }, tableName, new Integer[] { 0, 0 });
696
697 util.deleteTable(tableName);
698 table.close();
699 }
700
701
702 private void verifyMethodResult(Class<?> c, String methodName[], TableName tableName,
703 Object value[]) throws IOException {
704 try {
705 for (JVMClusterUtil.RegionServerThread t : cluster.getRegionServerThreads()) {
706 if (!t.isAlive() || t.getRegionServer().isAborted() || t.getRegionServer().isStopping()){
707 continue;
708 }
709 for (HRegionInfo r : ProtobufUtil.getOnlineRegions(t.getRegionServer())) {
710 if (!r.getTable().equals(tableName)) {
711 continue;
712 }
713 RegionCoprocessorHost cph = t.getRegionServer().getOnlineRegion(r.getRegionName()).
714 getCoprocessorHost();
715
716 Coprocessor cp = cph.findCoprocessor(c.getName());
717 assertNotNull(cp);
718 for (int i = 0; i < methodName.length; ++i) {
719 Method m = c.getMethod(methodName[i]);
720 Object o = m.invoke(cp);
721 assertTrue("Result of " + c.getName() + "." + methodName[i]
722 + " is expected to be " + value[i].toString()
723 + ", while we get " + o.toString(), o.equals(value[i]));
724 }
725 }
726 }
727 } catch (Exception e) {
728 throw new IOException(e.toString());
729 }
730 }
731
732 private static void createHFile(
733 Configuration conf,
734 FileSystem fs, Path path,
735 byte[] family, byte[] qualifier) throws IOException {
736 HFileContext context = new HFileContextBuilder().build();
737 HFile.Writer writer = HFile.getWriterFactory(conf, new CacheConfig(conf))
738 .withPath(fs, path)
739 .withFileContext(context)
740 .create();
741 long now = System.currentTimeMillis();
742 try {
743 for (int i =1;i<=9;i++) {
744 KeyValue kv = new KeyValue(Bytes.toBytes(i+""), family, qualifier, now, Bytes.toBytes(i+""));
745 writer.append(kv);
746 }
747 } finally {
748 writer.close();
749 }
750 }
751
752 }