1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.util;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.fs.FileSystem;
27 import org.apache.hadoop.fs.Path;
28 import org.apache.hadoop.hbase.HBaseConfiguration;
29 import org.apache.hadoop.hbase.HColumnDescriptor;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.client.Delete;
32 import org.apache.hadoop.hbase.client.Get;
33 import org.apache.hadoop.hbase.client.HTable;
34 import org.apache.hadoop.hbase.client.Put;
35 import org.apache.hadoop.hbase.client.Result;
36 import org.apache.hadoop.hbase.client.Scan;
37 import org.apache.hadoop.hbase.regionserver.HRegion;
38 import org.apache.hadoop.hbase.regionserver.InternalScanner;
39 import org.apache.hadoop.hbase.regionserver.Store;
40 import org.apache.hadoop.hbase.regionserver.wal.HLog;
41 import org.apache.hadoop.hbase.HRegionInfo;
42 import org.apache.hadoop.hbase.KeyValue;
43
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.TreeMap;
50
51
52
53
54
55
56
57
58 public class MetaUtils {
59 private static final Log LOG = LogFactory.getLog(MetaUtils.class);
60 private final Configuration conf;
61 private FileSystem fs;
62 private Path rootdir;
63 private HLog log;
64 private HRegion rootRegion;
65 private Map<byte [], HRegion> metaRegions = Collections.synchronizedSortedMap(
66 new TreeMap<byte [], HRegion>(Bytes.BYTES_COMPARATOR));
67
68
69
70
71 public MetaUtils() throws IOException {
72 this(HBaseConfiguration.create());
73 }
74
75
76
77
78
79 public MetaUtils(Configuration conf) throws IOException {
80 this.conf = conf;
81 conf.setInt("hbase.client.retries.number", 1);
82 this.rootRegion = null;
83 initialize();
84 }
85
86
87
88
89
90 private void initialize() throws IOException {
91 this.fs = FileSystem.get(this.conf);
92
93 this.rootdir = FSUtils.getRootDir(this.conf);
94 }
95
96
97
98
99
100 public synchronized HLog getLog() throws IOException {
101 if (this.log == null) {
102 Path logdir = new Path(this.fs.getHomeDirectory(),
103 HConstants.HREGION_LOGDIR_NAME + "_" + System.currentTimeMillis());
104 Path oldLogDir = new Path(this.fs.getHomeDirectory(),
105 HConstants.HREGION_OLDLOGDIR_NAME);
106 this.log = new HLog(this.fs, logdir, oldLogDir, this.conf);
107 }
108 return this.log;
109 }
110
111
112
113
114
115 public HRegion getRootRegion() throws IOException {
116 if (this.rootRegion == null) {
117 openRootRegion();
118 }
119 return this.rootRegion;
120 }
121
122
123
124
125
126
127
128
129 public HRegion getMetaRegion(HRegionInfo metaInfo) throws IOException {
130 HRegion meta = metaRegions.get(metaInfo.getRegionName());
131 if (meta == null) {
132 meta = openMetaRegion(metaInfo);
133 LOG.info("OPENING META " + meta.toString());
134 this.metaRegions.put(metaInfo.getRegionName(), meta);
135 }
136 return meta;
137 }
138
139
140
141
142
143
144 public void shutdown() {
145 if (this.rootRegion != null) {
146 try {
147 this.rootRegion.close();
148 } catch (IOException e) {
149 LOG.error("closing root region", e);
150 } finally {
151 this.rootRegion = null;
152 }
153 }
154 try {
155 for (HRegion r: metaRegions.values()) {
156 LOG.info("CLOSING META " + r.toString());
157 r.close();
158 }
159 } catch (IOException e) {
160 LOG.error("closing meta region", e);
161 } finally {
162 metaRegions.clear();
163 }
164 try {
165 if (this.log != null) {
166 this.log.rollWriter();
167 this.log.closeAndDelete();
168 }
169 } catch (IOException e) {
170 LOG.error("closing HLog", e);
171 } finally {
172 this.log = null;
173 }
174 }
175
176
177
178
179
180 public interface ScannerListener {
181
182
183
184
185
186
187
188 public boolean processRow(HRegionInfo info) throws IOException;
189 }
190
191
192
193
194
195
196
197
198 public void scanRootRegion(ScannerListener listener) throws IOException {
199
200 if (this.rootRegion == null) {
201 openRootRegion();
202 }
203 scanMetaRegion(this.rootRegion, listener);
204 }
205
206
207
208
209
210
211
212
213 public void scanMetaRegion(final HRegion r, final ScannerListener listener)
214 throws IOException {
215 Scan scan = new Scan();
216 scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
217 InternalScanner s = r.getScanner(scan);
218 try {
219 List<KeyValue> results = new ArrayList<KeyValue>();
220 boolean hasNext = true;
221 do {
222 hasNext = s.next(results);
223 HRegionInfo info = null;
224 for (KeyValue kv: results) {
225 info = Writables.getHRegionInfoOrNull(kv.getValue());
226 if (info == null) {
227 LOG.warn("Region info is null for row " +
228 Bytes.toStringBinary(kv.getRow()) + " in table " +
229 r.getTableDesc().getNameAsString());
230 }
231 continue;
232 }
233 if (!listener.processRow(info)) {
234 break;
235 }
236 results.clear();
237 } while (hasNext);
238 } finally {
239 s.close();
240 }
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257 public void scanMetaRegion(HRegionInfo metaRegionInfo,
258 ScannerListener listener)
259 throws IOException {
260
261 HRegion metaRegion = openMetaRegion(metaRegionInfo);
262 scanMetaRegion(metaRegion, listener);
263 }
264
265 private synchronized HRegion openRootRegion() throws IOException {
266 if (this.rootRegion != null) {
267 return this.rootRegion;
268 }
269 this.rootRegion = HRegion.openHRegion(HRegionInfo.ROOT_REGIONINFO, getLog(),
270 this.conf);
271 this.rootRegion.compactStores();
272 return this.rootRegion;
273 }
274
275 private HRegion openMetaRegion(HRegionInfo metaInfo) throws IOException {
276 HRegion meta = HRegion.openHRegion(metaInfo, getLog(), this.conf);
277 meta.compactStores();
278 return meta;
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 public static void changeOnlineStatus (final Configuration c,
295 final byte [] row, final boolean onlineOffline)
296 throws IOException {
297 HTable t = new HTable(c, HConstants.META_TABLE_NAME);
298 Get get = new Get(row);
299 get.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
300 Result res = t.get(get);
301 KeyValue [] kvs = res.raw();
302 if(kvs.length <= 0) {
303 throw new IOException("no information for row " + Bytes.toString(row));
304 }
305 byte [] value = kvs[0].getValue();
306 if (value == null) {
307 throw new IOException("no information for row " + Bytes.toString(row));
308 }
309 HRegionInfo info = Writables.getHRegionInfo(value);
310 Put put = new Put(row);
311 info.setOffline(onlineOffline);
312 put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
313 Writables.getBytes(info));
314 t.put(put);
315
316 Delete delete = new Delete(row);
317 delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER);
318 delete.deleteColumns(HConstants.CATALOG_FAMILY,
319 HConstants.STARTCODE_QUALIFIER);
320
321 t.delete(delete);
322 }
323
324
325
326
327
328
329
330
331 public void addColumn(final byte [] tableName,
332 final HColumnDescriptor hcd)
333 throws IOException {
334 List<HRegionInfo> metas = getMETARows(tableName);
335 for (HRegionInfo hri: metas) {
336 final HRegion m = getMetaRegion(hri);
337 scanMetaRegion(m, new ScannerListener() {
338 private boolean inTable = true;
339
340 @SuppressWarnings("synthetic-access")
341 public boolean processRow(HRegionInfo info) throws IOException {
342 LOG.debug("Testing " + Bytes.toString(tableName) + " against " +
343 Bytes.toString(info.getTableDesc().getName()));
344 if (Bytes.equals(info.getTableDesc().getName(), tableName)) {
345 this.inTable = false;
346 info.getTableDesc().addFamily(hcd);
347 updateMETARegionInfo(m, info);
348 return true;
349 }
350
351
352
353 return this.inTable;
354 }});
355 }
356 }
357
358
359
360
361
362
363
364
365 public void deleteColumn(final byte [] tableName,
366 final byte [] columnFamily) throws IOException {
367 List<HRegionInfo> metas = getMETARows(tableName);
368 for (HRegionInfo hri: metas) {
369 final HRegion m = getMetaRegion(hri);
370 scanMetaRegion(m, new ScannerListener() {
371 private boolean inTable = true;
372
373 @SuppressWarnings("synthetic-access")
374 public boolean processRow(HRegionInfo info) throws IOException {
375 if (Bytes.equals(info.getTableDesc().getName(), tableName)) {
376 this.inTable = false;
377 info.getTableDesc().removeFamily(columnFamily);
378 updateMETARegionInfo(m, info);
379 Path tabledir = new Path(rootdir,
380 info.getTableDesc().getNameAsString());
381 Path p = Store.getStoreHomedir(tabledir, info.getEncodedName(),
382 columnFamily);
383 if (!fs.delete(p, true)) {
384 LOG.warn("Failed delete of " + p);
385 }
386 return false;
387 }
388
389
390
391 return this.inTable;
392 }});
393 }
394 }
395
396
397
398
399
400
401
402
403 public void updateMETARegionInfo(HRegion r, final HRegionInfo hri)
404 throws IOException {
405 if (LOG.isDebugEnabled()) {
406 Get get = new Get(hri.getRegionName());
407 get.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
408 Result res = r.get(get, null);
409 KeyValue [] kvs = res.raw();
410 if(kvs.length <= 0) {
411 return;
412 }
413 byte [] value = kvs[0].getValue();
414 if (value == null) {
415 return;
416 }
417 HRegionInfo h = Writables.getHRegionInfoOrNull(value);
418
419 LOG.debug("Old " + Bytes.toString(HConstants.CATALOG_FAMILY) + ":" +
420 Bytes.toString(HConstants.REGIONINFO_QUALIFIER) + " for " +
421 hri.toString() + " in " + r.toString() + " is: " + h.toString());
422 }
423
424 Put put = new Put(hri.getRegionName());
425 put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
426 Writables.getBytes(hri));
427 r.put(put);
428
429 if (LOG.isDebugEnabled()) {
430 Get get = new Get(hri.getRegionName());
431 get.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
432 Result res = r.get(get, null);
433 KeyValue [] kvs = res.raw();
434 if(kvs.length <= 0) {
435 return;
436 }
437 byte [] value = kvs[0].getValue();
438 if (value == null) {
439 return;
440 }
441 HRegionInfo h = Writables.getHRegionInfoOrNull(value);
442 LOG.debug("New " + Bytes.toString(HConstants.CATALOG_FAMILY) + ":" +
443 Bytes.toString(HConstants.REGIONINFO_QUALIFIER) + " for " +
444 hri.toString() + " in " + r.toString() + " is: " + h.toString());
445 }
446 }
447
448
449
450
451
452
453
454
455 public List<HRegionInfo> getMETARows(final byte [] tableName)
456 throws IOException {
457 final List<HRegionInfo> result = new ArrayList<HRegionInfo>();
458
459 if (Bytes.equals(HConstants.META_TABLE_NAME, tableName)) {
460 result.add(openRootRegion().getRegionInfo());
461 return result;
462 }
463
464 scanRootRegion(new ScannerListener() {
465 private final Log SL_LOG = LogFactory.getLog(this.getClass());
466
467 public boolean processRow(HRegionInfo info) throws IOException {
468 SL_LOG.debug("Testing " + info);
469 if (Bytes.equals(info.getTableDesc().getName(),
470 HConstants.META_TABLE_NAME)) {
471 result.add(info);
472 return false;
473 }
474 return true;
475 }});
476 return result;
477 }
478 }