1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.coprocessor;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertTrue;
23
24 import java.io.IOException;
25 import java.util.List;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.hbase.Coprocessor;
31 import org.apache.hadoop.hbase.HBaseConfiguration;
32 import org.apache.hadoop.hbase.HBaseTestingUtility;
33 import org.apache.hadoop.hbase.HColumnDescriptor;
34 import org.apache.hadoop.hbase.HTableDescriptor;
35 import org.apache.hadoop.hbase.testclassification.MediumTests;
36 import org.apache.hadoop.hbase.MiniHBaseCluster;
37 import org.apache.hadoop.hbase.TableName;
38 import org.apache.hadoop.hbase.MetaTableAccessor;
39 import org.apache.hadoop.hbase.client.Admin;
40 import org.apache.hadoop.hbase.client.HBaseAdmin;
41 import org.apache.hadoop.hbase.client.Mutation;
42 import org.apache.hadoop.hbase.regionserver.HRegion;
43 import org.apache.hadoop.hbase.regionserver.HRegionServer;
44 import org.apache.hadoop.hbase.regionserver.RegionMergeTransaction;
45 import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
46 import org.apache.hadoop.hbase.util.Bytes;
47 import org.junit.Test;
48 import org.junit.experimental.categories.Category;
49
50
51
52
53
54 @Category(MediumTests.class)
55 public class TestRegionServerObserver {
56 private static final Log LOG = LogFactory.getLog(TestRegionServerObserver.class);
57
58
59
60
61
62 @Test
63 public void testCoprocessorHooksInRegionsMerge() throws Exception {
64 final int NUM_MASTERS = 1;
65 final int NUM_RS = 1;
66 final String TABLENAME = "testRegionServerObserver";
67 final String TABLENAME2 = "testRegionServerObserver_2";
68 final byte[] FAM = Bytes.toBytes("fam");
69
70
71 Configuration conf = HBaseConfiguration.create();
72 conf.setClass("hbase.coprocessor.regionserver.classes", CPRegionServerObserver.class,
73 RegionServerObserver.class);
74
75
76 HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(conf);
77 TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS);
78 Admin admin = new HBaseAdmin(conf);
79 try {
80 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
81 HRegionServer regionServer = cluster.getRegionServer(0);
82 RegionServerCoprocessorHost cpHost = regionServer.getRegionServerCoprocessorHost();
83 Coprocessor coprocessor = cpHost.findCoprocessor(CPRegionServerObserver.class.getName());
84 CPRegionServerObserver regionServerObserver = (CPRegionServerObserver) coprocessor;
85 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(TABLENAME));
86 desc.addFamily(new HColumnDescriptor(FAM));
87 admin.createTable(desc, new byte[][] { Bytes.toBytes("row") });
88 desc = new HTableDescriptor(TableName.valueOf(TABLENAME2));
89 desc.addFamily(new HColumnDescriptor(FAM));
90 admin.createTable(desc, new byte[][] { Bytes.toBytes("row") });
91 assertFalse(regionServerObserver.wasRegionMergeCalled());
92 List<HRegion> regions = regionServer.getOnlineRegions(TableName.valueOf(TABLENAME));
93 admin.mergeRegions(regions.get(0).getRegionInfo().getEncodedNameAsBytes(), regions.get(1)
94 .getRegionInfo().getEncodedNameAsBytes(), true);
95 int regionsCount = regionServer.getOnlineRegions(TableName.valueOf(TABLENAME)).size();
96 while (regionsCount != 1) {
97 regionsCount = regionServer.getOnlineRegions(TableName.valueOf(TABLENAME)).size();
98 Thread.sleep(1000);
99 }
100 assertTrue(regionServerObserver.wasRegionMergeCalled());
101 assertTrue(regionServerObserver.wasPreMergeCommit());
102 assertTrue(regionServerObserver.wasPostMergeCommit());
103 assertEquals(regionsCount, 1);
104 assertEquals(regionServer.getOnlineRegions(TableName.valueOf(TABLENAME2)).size(), 1);
105 } finally {
106 if (admin != null) admin.close();
107 TEST_UTIL.shutdownMiniCluster();
108 }
109 }
110
111 public static class CPRegionServerObserver extends BaseRegionServerObserver {
112 private RegionMergeTransaction rmt = null;
113 private HRegion mergedRegion = null;
114
115 private boolean preMergeCalled;
116 private boolean preMergeBeforePONRCalled;
117 private boolean preMergeAfterPONRCalled;
118 private boolean preRollBackMergeCalled;
119 private boolean postRollBackMergeCalled;
120 private boolean postMergeCalled;
121
122 public void resetStates() {
123 preMergeCalled = false;
124 preMergeBeforePONRCalled = false;
125 preMergeAfterPONRCalled = false;
126 preRollBackMergeCalled = false;
127 postRollBackMergeCalled = false;
128 postMergeCalled = false;
129 }
130
131 @Override
132 public void preMerge(ObserverContext<RegionServerCoprocessorEnvironment> ctx, HRegion regionA,
133 HRegion regionB) throws IOException {
134 preMergeCalled = true;
135 }
136
137 @Override
138 public void preMergeCommit(ObserverContext<RegionServerCoprocessorEnvironment> ctx,
139 HRegion regionA, HRegion regionB, List<Mutation> metaEntries) throws IOException {
140 preMergeBeforePONRCalled = true;
141 RegionServerCoprocessorEnvironment environment = ctx.getEnvironment();
142 HRegionServer rs = (HRegionServer) environment.getRegionServerServices();
143 List<HRegion> onlineRegions =
144 rs.getOnlineRegions(TableName.valueOf("testRegionServerObserver_2"));
145 rmt = new RegionMergeTransaction(onlineRegions.get(0), onlineRegions.get(1), true);
146 if (!rmt.prepare(rs)) {
147 LOG.error("Prepare for the region merge of table "
148 + onlineRegions.get(0).getTableDesc().getNameAsString()
149 + " failed. So returning null. ");
150 ctx.bypass();
151 return;
152 }
153 mergedRegion = rmt.stepsBeforePONR(rs, rs, false);
154 rmt.prepareMutationsForMerge(mergedRegion.getRegionInfo(), regionA.getRegionInfo(),
155 regionB.getRegionInfo(), rs.getServerName(), metaEntries);
156 MetaTableAccessor.mutateMetaTable(rs.getConnection(), metaEntries);
157 }
158
159 @Override
160 public void postMergeCommit(ObserverContext<RegionServerCoprocessorEnvironment> ctx,
161 HRegion regionA, HRegion regionB, HRegion mr) throws IOException {
162 preMergeAfterPONRCalled = true;
163 RegionServerCoprocessorEnvironment environment = ctx.getEnvironment();
164 HRegionServer rs = (HRegionServer) environment.getRegionServerServices();
165 rmt.stepsAfterPONR(rs, rs, this.mergedRegion);
166 }
167
168 @Override
169 public void preRollBackMerge(ObserverContext<RegionServerCoprocessorEnvironment> ctx,
170 HRegion regionA, HRegion regionB) throws IOException {
171 preRollBackMergeCalled = true;
172 }
173
174 @Override
175 public void postRollBackMerge(ObserverContext<RegionServerCoprocessorEnvironment> ctx,
176 HRegion regionA, HRegion regionB) throws IOException {
177 postRollBackMergeCalled = true;
178 }
179
180 @Override
181 public void postMerge(ObserverContext<RegionServerCoprocessorEnvironment> c, HRegion regionA,
182 HRegion regionB, HRegion mergedRegion) throws IOException {
183 postMergeCalled = true;
184 }
185
186 public boolean wasPreMergeCalled() {
187 return this.preMergeCalled;
188 }
189
190 public boolean wasPostMergeCalled() {
191 return this.postMergeCalled;
192 }
193
194 public boolean wasPreMergeCommit() {
195 return this.preMergeBeforePONRCalled;
196 }
197
198 public boolean wasPostMergeCommit() {
199 return this.preMergeAfterPONRCalled;
200 }
201
202 public boolean wasPreRollBackMerge() {
203 return this.preRollBackMergeCalled;
204 }
205
206 public boolean wasPostRollBackMerge() {
207 return this.postRollBackMergeCalled;
208 }
209
210 public boolean wasRegionMergeCalled() {
211 return this.preMergeCalled && this.postMergeCalled;
212 }
213
214 }
215
216 }