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