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