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.util;
21
22 import java.io.IOException;
23 import java.io.InterruptedIOException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.concurrent.Callable;
28 import java.util.concurrent.CompletionService;
29 import java.util.concurrent.ExecutionException;
30 import java.util.concurrent.ExecutorCompletionService;
31 import java.util.concurrent.Future;
32 import java.util.concurrent.ThreadFactory;
33 import java.util.concurrent.ThreadPoolExecutor;
34 import java.util.concurrent.TimeUnit;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.hadoop.hbase.classification.InterfaceAudience;
39 import org.apache.hadoop.conf.Configuration;
40 import org.apache.hadoop.fs.Path;
41 import org.apache.hadoop.hbase.HRegionInfo;
42 import org.apache.hadoop.hbase.HTableDescriptor;
43 import org.apache.hadoop.hbase.regionserver.HRegion;
44
45
46
47
48 @InterfaceAudience.Private
49 public abstract class ModifyRegionUtils {
50 private static final Log LOG = LogFactory.getLog(ModifyRegionUtils.class);
51
52 private ModifyRegionUtils() {
53 }
54
55 public interface RegionFillTask {
56 void fillRegion(final HRegion region) throws IOException;
57 }
58
59 public interface RegionEditTask {
60 void editRegion(final HRegionInfo region) throws IOException;
61 }
62
63
64
65
66
67
68
69
70
71
72
73 public static List<HRegionInfo> createRegions(final Configuration conf, final Path rootDir,
74 final HTableDescriptor hTableDescriptor, final HRegionInfo[] newRegions) throws IOException {
75 return createRegions(conf, rootDir, hTableDescriptor, newRegions, null);
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89 public static List<HRegionInfo> createRegions(final Configuration conf, final Path rootDir,
90 final HTableDescriptor hTableDescriptor, final HRegionInfo[] newRegions,
91 final RegionFillTask task) throws IOException {
92
93 Path tableDir = FSUtils.getTableDir(rootDir, hTableDescriptor.getTableName());
94 return createRegions(conf, rootDir, tableDir, hTableDescriptor, newRegions, task);
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108
109 public static List<HRegionInfo> createRegions(final Configuration conf, final Path rootDir,
110 final Path tableDir, final HTableDescriptor hTableDescriptor, final HRegionInfo[] newRegions,
111 final RegionFillTask task) throws IOException {
112 if (newRegions == null) return null;
113 int regionNumber = newRegions.length;
114 ThreadPoolExecutor exec = getRegionOpenAndInitThreadPool(conf,
115 "RegionOpenAndInitThread-" + hTableDescriptor.getTableName(), regionNumber);
116 try {
117 return createRegions(exec, conf, rootDir, tableDir, hTableDescriptor, newRegions, task);
118 } finally {
119 exec.shutdownNow();
120 }
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public static List<HRegionInfo> createRegions(final ThreadPoolExecutor exec,
137 final Configuration conf, final Path rootDir, final Path tableDir,
138 final HTableDescriptor hTableDescriptor, final HRegionInfo[] newRegions,
139 final RegionFillTask task) throws IOException {
140 if (newRegions == null) return null;
141 int regionNumber = newRegions.length;
142 CompletionService<HRegionInfo> completionService =
143 new ExecutorCompletionService<HRegionInfo>(exec);
144 List<HRegionInfo> regionInfos = new ArrayList<HRegionInfo>();
145 for (final HRegionInfo newRegion : newRegions) {
146 completionService.submit(new Callable<HRegionInfo>() {
147 @Override
148 public HRegionInfo call() throws IOException {
149 return createRegion(conf, rootDir, tableDir, hTableDescriptor, newRegion, task);
150 }
151 });
152 }
153 try {
154
155 for (int i = 0; i < regionNumber; i++) {
156 Future<HRegionInfo> future = completionService.take();
157 HRegionInfo regionInfo = future.get();
158 regionInfos.add(regionInfo);
159 }
160 } catch (InterruptedException e) {
161 LOG.error("Caught " + e + " during region creation");
162 throw new InterruptedIOException(e.getMessage());
163 } catch (ExecutionException e) {
164 throw new IOException(e);
165 }
166 return regionInfos;
167 }
168
169
170
171
172
173
174
175
176
177
178
179 public static HRegionInfo createRegion(final Configuration conf, final Path rootDir,
180 final Path tableDir, final HTableDescriptor hTableDescriptor, final HRegionInfo newRegion,
181 final RegionFillTask task) throws IOException {
182
183 HRegion region = HRegion.createHRegion(newRegion,
184 rootDir, tableDir, conf, hTableDescriptor, null,
185 false, true);
186 try {
187
188 if (task != null) {
189 task.fillRegion(region);
190 }
191 } finally {
192
193 region.close();
194 }
195 return region.getRegionInfo();
196 }
197
198
199
200
201
202
203
204
205
206 public static void editRegions(final ThreadPoolExecutor exec,
207 final Collection<HRegionInfo> regions, final RegionEditTask task) throws IOException {
208 final ExecutorCompletionService<Void> completionService =
209 new ExecutorCompletionService<Void>(exec);
210 for (final HRegionInfo hri: regions) {
211 completionService.submit(new Callable<Void>() {
212 @Override
213 public Void call() throws IOException {
214 task.editRegion(hri);
215 return null;
216 }
217 });
218 }
219
220 try {
221 for (HRegionInfo hri: regions) {
222 completionService.take().get();
223 }
224 } catch (InterruptedException e) {
225 throw new InterruptedIOException(e.getMessage());
226 } catch (ExecutionException e) {
227 IOException ex = new IOException();
228 ex.initCause(e.getCause());
229 throw ex;
230 }
231 }
232
233
234
235
236
237 static ThreadPoolExecutor getRegionOpenAndInitThreadPool(final Configuration conf,
238 final String threadNamePrefix, int regionNumber) {
239 int maxThreads = Math.min(regionNumber, conf.getInt(
240 "hbase.hregion.open.and.init.threads.max", 10));
241 ThreadPoolExecutor regionOpenAndInitThreadPool = Threads
242 .getBoundedCachedThreadPool(maxThreads, 30L, TimeUnit.SECONDS,
243 new ThreadFactory() {
244 private int count = 1;
245
246 @Override
247 public Thread newThread(Runnable r) {
248 Thread t = new Thread(r, threadNamePrefix + "-" + count++);
249 return t;
250 }
251 });
252 return regionOpenAndInitThreadPool;
253 }
254 }