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;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.concurrent.ConcurrentHashMap;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.fs.FileSystem;
32 import org.apache.hadoop.hbase.client.HConnectionManager;
33 import org.apache.hadoop.hbase.master.HMaster;
34 import org.apache.hadoop.hbase.regionserver.HRegion;
35 import org.apache.hadoop.hbase.regionserver.HRegionServer;
36 import org.apache.hadoop.hbase.util.Bytes;
37 import org.apache.hadoop.hbase.util.JVMClusterUtil;
38 import org.apache.hadoop.hbase.util.Threads;
39 import org.apache.hadoop.hdfs.DistributedFileSystem;
40 import org.apache.hadoop.io.MapWritable;
41 import org.apache.hadoop.security.UnixUserGroupInformation;
42 import org.apache.hadoop.security.UserGroupInformation;
43
44
45
46
47
48
49
50 public class MiniHBaseCluster {
51 static final Log LOG = LogFactory.getLog(MiniHBaseCluster.class.getName());
52 private Configuration conf;
53 public LocalHBaseCluster hbaseCluster;
54
55
56 private final static UserGroupInformation UGI;
57 static {
58 UGI = UserGroupInformation.getCurrentUGI();
59 }
60
61
62
63
64
65
66
67 public MiniHBaseCluster(Configuration conf, int numRegionServers)
68 throws IOException {
69 this.conf = conf;
70 conf.set(HConstants.MASTER_PORT, "0");
71 init(numRegionServers);
72 }
73
74
75
76
77 public static class MiniHBaseClusterMaster extends HMaster {
78 private final Map<HServerInfo, List<HMsg>> messages =
79 new ConcurrentHashMap<HServerInfo, List<HMsg>>();
80
81 private final Map<HServerInfo, IOException> exceptions =
82 new ConcurrentHashMap<HServerInfo, IOException>();
83
84 public MiniHBaseClusterMaster(final Configuration conf)
85 throws IOException {
86 super(conf);
87 }
88
89
90
91
92
93
94 void addMessage(final HServerInfo hsi, HMsg msg) {
95 synchronized(this.messages) {
96 List<HMsg> hmsgs = this.messages.get(hsi);
97 if (hmsgs == null) {
98 hmsgs = new ArrayList<HMsg>();
99 this.messages.put(hsi, hmsgs);
100 }
101 hmsgs.add(msg);
102 }
103 }
104
105 void addException(final HServerInfo hsi, final IOException ex) {
106 this.exceptions.put(hsi, ex);
107 }
108
109
110
111
112
113
114
115
116
117
118 @Override
119 protected HMsg[] adornRegionServerAnswer(final HServerInfo hsi,
120 final HMsg[] msgs) throws IOException {
121 IOException ex = this.exceptions.remove(hsi);
122 if (ex != null) {
123 throw ex;
124 }
125 HMsg [] answerMsgs = msgs;
126 synchronized (this.messages) {
127 List<HMsg> hmsgs = this.messages.get(hsi);
128 if (hmsgs != null && !hmsgs.isEmpty()) {
129 int size = answerMsgs.length;
130 HMsg [] newAnswerMsgs = new HMsg[size + hmsgs.size()];
131 System.arraycopy(answerMsgs, 0, newAnswerMsgs, 0, answerMsgs.length);
132 for (int i = 0; i < hmsgs.size(); i++) {
133 newAnswerMsgs[answerMsgs.length + i] = hmsgs.get(i);
134 }
135 answerMsgs = newAnswerMsgs;
136 hmsgs.clear();
137 }
138 }
139 return super.adornRegionServerAnswer(hsi, answerMsgs);
140 }
141 }
142
143
144
145
146
147
148
149 public static class MiniHBaseClusterRegionServer extends HRegionServer {
150 private static int index = 0;
151 private Thread shutdownThread = null;
152
153 public MiniHBaseClusterRegionServer(Configuration conf)
154 throws IOException {
155 super(setDifferentUser(conf));
156 }
157
158 public void setHServerInfo(final HServerInfo hsi) {
159 this.serverInfo = hsi;
160 }
161
162
163
164
165
166
167
168
169 private static Configuration setDifferentUser(final Configuration c)
170 throws IOException {
171 FileSystem currentfs = FileSystem.get(c);
172 if (!(currentfs instanceof DistributedFileSystem)) return c;
173
174
175 Configuration c2 = new Configuration(c);
176 String username = UGI.getUserName() + ".hrs." + index++;
177 UnixUserGroupInformation.saveToConf(c2,
178 UnixUserGroupInformation.UGI_PROPERTY_NAME,
179 new UnixUserGroupInformation(username, new String[]{"supergroup"}));
180 return c2;
181 }
182
183 @Override
184 protected void init(MapWritable c) throws IOException {
185 super.init(c);
186
187 this.shutdownThread = new SingleFileSystemShutdownThread(getFileSystem());
188 }
189
190 @Override
191 public void run() {
192 try {
193 super.run();
194 } finally {
195
196 if (this.shutdownThread != null) {
197 this.shutdownThread.start();
198 Threads.shutdown(this.shutdownThread, 30000);
199 }
200 }
201 }
202
203 public void kill() {
204 super.kill();
205 }
206 }
207
208
209
210
211
212 static class SingleFileSystemShutdownThread extends Thread {
213 private final FileSystem fs;
214 SingleFileSystemShutdownThread(final FileSystem fs) {
215 super("Shutdown of " + fs);
216 this.fs = fs;
217 }
218 @Override
219 public void run() {
220 try {
221 LOG.info("Hook closing fs=" + this.fs);
222 this.fs.close();
223 } catch (IOException e) {
224 LOG.warn("Running hook", e);
225 }
226 }
227 }
228
229 private void init(final int nRegionNodes) throws IOException {
230 try {
231
232 hbaseCluster = new LocalHBaseCluster(conf, nRegionNodes,
233 MiniHBaseCluster.MiniHBaseClusterMaster.class,
234 MiniHBaseCluster.MiniHBaseClusterRegionServer.class);
235 hbaseCluster.startup();
236 } catch(IOException e) {
237 shutdown();
238 throw e;
239 }
240 }
241
242
243
244
245
246
247
248 public JVMClusterUtil.RegionServerThread startRegionServer() throws IOException {
249 JVMClusterUtil.RegionServerThread t = this.hbaseCluster.addRegionServer();
250 t.start();
251 t.waitForServerOnline();
252 return t;
253 }
254
255
256
257
258
259 public HServerAddress getHMasterAddress() {
260 return this.hbaseCluster.getMaster().getMasterAddress();
261 }
262
263
264
265
266 public HMaster getMaster() {
267 return this.hbaseCluster.getMaster();
268 }
269
270
271
272
273
274 public String abortRegionServer(int serverNumber) {
275 HRegionServer server = getRegionServer(serverNumber);
276 LOG.info("Aborting " + server.toString());
277 server.abort("Aborting for tests", new Exception("Trace info"));
278 return server.toString();
279 }
280
281
282
283
284
285
286
287 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber) {
288 return stopRegionServer(serverNumber, true);
289 }
290
291
292
293
294
295
296
297
298
299
300
301 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber,
302 final boolean shutdownFS) {
303 JVMClusterUtil.RegionServerThread server =
304 hbaseCluster.getRegionServers().get(serverNumber);
305 LOG.info("Stopping " + server.toString());
306 server.getRegionServer().stop();
307 return server;
308 }
309
310
311
312
313
314
315
316 public String waitOnRegionServer(final int serverNumber) {
317 return this.hbaseCluster.waitOnRegionServer(serverNumber);
318 }
319
320
321
322
323 public void join() {
324 this.hbaseCluster.join();
325 }
326
327
328
329
330
331 public void shutdown() throws IOException {
332 if (this.hbaseCluster != null) {
333 this.hbaseCluster.shutdown();
334 }
335 HConnectionManager.deleteAllConnections(false);
336 }
337
338
339
340
341
342 public void flushcache() throws IOException {
343 for (JVMClusterUtil.RegionServerThread t:
344 this.hbaseCluster.getRegionServers()) {
345 for(HRegion r: t.getRegionServer().getOnlineRegions()) {
346 r.flushcache();
347 }
348 }
349 }
350
351
352
353
354
355 public void flushcache(byte [] tableName) throws IOException {
356 for (JVMClusterUtil.RegionServerThread t:
357 this.hbaseCluster.getRegionServers()) {
358 for(HRegion r: t.getRegionServer().getOnlineRegions()) {
359 if(Bytes.equals(r.getTableDesc().getName(), tableName)) {
360 r.flushcache();
361 }
362 }
363 }
364 }
365
366
367
368
369 public List<JVMClusterUtil.RegionServerThread> getRegionServerThreads() {
370 return this.hbaseCluster.getRegionServers();
371 }
372
373
374
375
376 public List<JVMClusterUtil.RegionServerThread> getLiveRegionServerThreads() {
377 return this.hbaseCluster.getLiveRegionServers();
378 }
379
380
381
382
383
384
385 public HRegionServer getRegionServer(int serverNumber) {
386 return hbaseCluster.getRegionServer(serverNumber);
387 }
388
389 public List<HRegion> getRegions(byte[] tableName) {
390 List<HRegion> ret = new ArrayList<HRegion>();
391 for (JVMClusterUtil.RegionServerThread rst : getRegionServerThreads()) {
392 HRegionServer hrs = rst.getRegionServer();
393 for (HRegion region : hrs.getOnlineRegions()) {
394 if (Bytes.equals(region.getTableDesc().getName(), tableName)) {
395 ret.add(region);
396 }
397 }
398 }
399 return ret;
400 }
401
402
403
404
405
406 public int getServerWithMeta() {
407 return getServerWith(HRegionInfo.FIRST_META_REGIONINFO.getRegionName());
408 }
409
410
411
412
413
414
415
416 public int getServerWith(byte[] regionName) {
417 int index = -1;
418 int count = 0;
419 for (JVMClusterUtil.RegionServerThread rst: getRegionServerThreads()) {
420 HRegionServer hrs = rst.getRegionServer();
421 HRegion metaRegion =
422 hrs.getOnlineRegion(regionName);
423 if (metaRegion != null) {
424 index = count;
425 break;
426 }
427 count++;
428 }
429 return index;
430 }
431
432
433
434
435
436
437
438 public void addExceptionToSendRegionServer(final int serverNumber,
439 IOException ex) throws IOException {
440 MiniHBaseClusterRegionServer hrs =
441 (MiniHBaseClusterRegionServer)getRegionServer(serverNumber);
442 addExceptionToSendRegionServer(hrs, ex);
443 }
444
445
446
447
448
449
450
451 public void addExceptionToSendRegionServer(
452 final MiniHBaseClusterRegionServer hrs, IOException ex)
453 throws IOException {
454 ((MiniHBaseClusterMaster)getMaster()).addException(hrs.getHServerInfo(),ex);
455 }
456
457
458
459
460
461
462
463
464 public void addMessageToSendRegionServer(final int serverNumber,
465 final HMsg msg)
466 throws IOException {
467 MiniHBaseClusterRegionServer hrs =
468 (MiniHBaseClusterRegionServer)getRegionServer(serverNumber);
469 addMessageToSendRegionServer(hrs, msg);
470 }
471
472
473
474
475
476
477
478
479 public void addMessageToSendRegionServer(final MiniHBaseClusterRegionServer hrs,
480 final HMsg msg)
481 throws IOException {
482 ((MiniHBaseClusterMaster)getMaster()).addMessage(hrs.getHServerInfo(), msg);
483 }
484 }