1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.catalog;
19
20 import java.io.IOException;
21 import java.io.InterruptedIOException;
22 import java.net.ConnectException;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.HConstants;
30 import org.apache.hadoop.hbase.HRegionInfo;
31 import org.apache.hadoop.hbase.ServerName;
32 import org.apache.hadoop.hbase.client.Delete;
33 import org.apache.hadoop.hbase.client.HTable;
34 import org.apache.hadoop.hbase.client.Mutation;
35 import org.apache.hadoop.hbase.client.Put;
36 import org.apache.hadoop.hbase.exceptions.DoNotRetryIOException;
37 import org.apache.hadoop.hbase.exceptions.NotAllMetaRegionsOnlineException;
38 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
39 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
40 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
41 import org.apache.hadoop.hbase.protobuf.generated.MultiRowMutation.MultiMutateRequest;
42 import org.apache.hadoop.hbase.protobuf.generated.MultiRowMutation.MultiRowMutationService;
43 import org.apache.hadoop.hbase.util.Bytes;
44
45 import com.google.protobuf.ServiceException;
46
47
48
49
50
51
52 @InterfaceAudience.Private
53 public class MetaEditor {
54
55
56
57 private static final Log LOG = LogFactory.getLog(MetaEditor.class);
58
59
60
61
62 public static Put makePutFromRegionInfo(HRegionInfo regionInfo)
63 throws IOException {
64 Put put = new Put(regionInfo.getRegionName());
65 addRegionInfo(put, regionInfo);
66 return put;
67 }
68
69
70
71
72
73 public static Delete makeDeleteFromRegionInfo(HRegionInfo regionInfo) {
74 if (regionInfo == null) {
75 throw new IllegalArgumentException("Can't make a delete for null region");
76 }
77 Delete delete = new Delete(regionInfo.getRegionName());
78 return delete;
79 }
80
81
82
83
84 public static Put addDaughtersToPut(Put put, HRegionInfo splitA, HRegionInfo splitB) {
85 if (splitA != null) {
86 put.add(HConstants.CATALOG_FAMILY, HConstants.SPLITA_QUALIFIER, splitA.toByteArray());
87 }
88 if (splitB != null) {
89 put.add(HConstants.CATALOG_FAMILY, HConstants.SPLITB_QUALIFIER, splitB.toByteArray());
90 }
91 return put;
92 }
93
94
95
96
97
98
99
100 static void putToMetaTable(final CatalogTracker ct, final Put p)
101 throws IOException {
102 put(MetaReader.getMetaHTable(ct), p);
103 }
104
105
106
107
108
109
110
111 static void putToCatalogTable(final CatalogTracker ct, final Put p)
112 throws IOException {
113 HTable t = MetaReader.getCatalogHTable(ct);
114 put(t, p);
115 }
116
117
118
119
120
121
122 private static void put(final HTable t, final Put p) throws IOException {
123 try {
124 t.put(p);
125 } finally {
126 t.close();
127 }
128 }
129
130
131
132
133
134
135
136 static void putsToMetaTable(final CatalogTracker ct, final List<Put> ps)
137 throws IOException {
138 HTable t = MetaReader.getMetaHTable(ct);
139 try {
140 t.put(ps);
141 } finally {
142 t.close();
143 }
144 }
145
146
147
148
149
150
151
152 static void deleteFromMetaTable(final CatalogTracker ct, final Delete d)
153 throws IOException {
154 List<Delete> dels = new ArrayList<Delete>(1);
155 dels.add(d);
156 deleteFromMetaTable(ct, dels);
157 }
158
159
160
161
162
163
164
165 public static void deleteFromMetaTable(final CatalogTracker ct, final List<Delete> deletes)
166 throws IOException {
167 HTable t = MetaReader.getMetaHTable(ct);
168 try {
169 t.delete(deletes);
170 } finally {
171 t.close();
172 }
173 }
174
175
176
177
178
179
180
181 static void mutateMetaTable(final CatalogTracker ct, final List<Mutation> mutations)
182 throws IOException {
183 HTable t = MetaReader.getMetaHTable(ct);
184 try {
185 t.batch(mutations);
186 } catch (InterruptedException e) {
187 InterruptedIOException ie = new InterruptedIOException(e.getMessage());
188 ie.initCause(e);
189 throw ie;
190 } finally {
191 t.close();
192 }
193 }
194
195
196
197
198
199
200 public static void addRegionToMeta(CatalogTracker catalogTracker,
201 HRegionInfo regionInfo)
202 throws IOException {
203 putToMetaTable(catalogTracker, makePutFromRegionInfo(regionInfo));
204 LOG.info("Added region " + regionInfo.getRegionNameAsString() + " to META");
205 }
206
207
208
209
210
211
212
213
214 public static void addRegionToMeta(HTable meta, HRegionInfo regionInfo) throws IOException {
215 addRegionToMeta(meta, regionInfo, null, null);
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230 public static void addRegionToMeta(HTable meta, HRegionInfo regionInfo,
231 HRegionInfo splitA, HRegionInfo splitB) throws IOException {
232 Put put = makePutFromRegionInfo(regionInfo);
233 addDaughtersToPut(put, splitA, splitB);
234 meta.put(put);
235 if (LOG.isDebugEnabled()) {
236 LOG.debug("Added region " + regionInfo.getRegionNameAsString() + " to META");
237 }
238 }
239
240
241
242
243
244
245
246 public static void addRegionsToMeta(CatalogTracker catalogTracker,
247 List<HRegionInfo> regionInfos)
248 throws IOException {
249 List<Put> puts = new ArrayList<Put>();
250 for (HRegionInfo regionInfo : regionInfos) {
251 puts.add(makePutFromRegionInfo(regionInfo));
252 }
253 putsToMetaTable(catalogTracker, puts);
254 LOG.info("Added " + puts.size() + " regions in META");
255 }
256
257
258
259
260
261
262
263 public static void addDaughter(final CatalogTracker catalogTracker,
264 final HRegionInfo regionInfo, final ServerName sn, final long openSeqNum)
265 throws NotAllMetaRegionsOnlineException, IOException {
266 Put put = new Put(regionInfo.getRegionName());
267 addRegionInfo(put, regionInfo);
268 if (sn != null) {
269 addLocation(put, sn, openSeqNum);
270 }
271 putToMetaTable(catalogTracker, put);
272 LOG.info("Added daughter " + regionInfo.getRegionNameAsString() +
273 (sn == null? ", serverName=null": ", serverName=" + sn.toString()));
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287 public static void mergeRegions(final CatalogTracker catalogTracker,
288 HRegionInfo mergedRegion, HRegionInfo regionA, HRegionInfo regionB,
289 ServerName sn) throws IOException {
290 HTable meta = MetaReader.getMetaHTable(catalogTracker);
291 HRegionInfo copyOfMerged = new HRegionInfo(mergedRegion);
292
293
294 Put putOfMerged = makePutFromRegionInfo(copyOfMerged);
295 putOfMerged.add(HConstants.CATALOG_FAMILY, HConstants.MERGEA_QUALIFIER,
296 regionA.toByteArray());
297 putOfMerged.add(HConstants.CATALOG_FAMILY, HConstants.MERGEB_QUALIFIER,
298 regionB.toByteArray());
299
300
301 Delete deleteA = makeDeleteFromRegionInfo(regionA);
302 Delete deleteB = makeDeleteFromRegionInfo(regionB);
303
304
305 addLocation(putOfMerged, sn, 1);
306
307 byte[] tableRow = Bytes.toBytes(mergedRegion.getRegionNameAsString()
308 + HConstants.DELIMITER);
309 multiMutate(meta, tableRow, putOfMerged, deleteA, deleteB);
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323 public static void splitRegion(final CatalogTracker catalogTracker,
324 HRegionInfo parent, HRegionInfo splitA, HRegionInfo splitB,
325 ServerName sn) throws IOException {
326 HTable meta = MetaReader.getMetaHTable(catalogTracker);
327 HRegionInfo copyOfParent = new HRegionInfo(parent);
328 copyOfParent.setOffline(true);
329 copyOfParent.setSplit(true);
330
331
332 Put putParent = makePutFromRegionInfo(copyOfParent);
333 addDaughtersToPut(putParent, splitA, splitB);
334
335
336 Put putA = makePutFromRegionInfo(splitA);
337 Put putB = makePutFromRegionInfo(splitB);
338
339 addLocation(putA, sn, 1);
340 addLocation(putB, sn, 1);
341
342 byte[] tableRow = Bytes.toBytes(parent.getRegionNameAsString() + HConstants.DELIMITER);
343 multiMutate(meta, tableRow, putParent, putA, putB);
344 }
345
346
347
348
349 private static void multiMutate(HTable table, byte[] row, Mutation... mutations) throws IOException {
350 CoprocessorRpcChannel channel = table.coprocessorService(row);
351 MultiMutateRequest.Builder mmrBuilder = MultiMutateRequest.newBuilder();
352 for (Mutation mutation : mutations) {
353 if (mutation instanceof Put) {
354 mmrBuilder.addMutationRequest(ProtobufUtil.toMutation(MutationType.PUT, mutation));
355 } else if (mutation instanceof Delete) {
356 mmrBuilder.addMutationRequest(ProtobufUtil.toMutation(MutationType.DELETE, mutation));
357 } else {
358 throw new DoNotRetryIOException("multi in MetaEditor doesn't support "
359 + mutation.getClass().getName());
360 }
361 }
362
363 MultiRowMutationService.BlockingInterface service =
364 MultiRowMutationService.newBlockingStub(channel);
365 try {
366 service.mutateRows(null, mmrBuilder.build());
367 } catch (ServiceException ex) {
368 ProtobufUtil.toIOException(ex);
369 }
370 }
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389 public static void updateMetaLocation(CatalogTracker catalogTracker,
390 HRegionInfo regionInfo, ServerName sn, long openSeqNum)
391 throws IOException, ConnectException {
392 updateLocation(catalogTracker, regionInfo, sn, openSeqNum);
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406
407 public static void updateRegionLocation(CatalogTracker catalogTracker,
408 HRegionInfo regionInfo, ServerName sn, long updateSeqNum)
409 throws IOException {
410 updateLocation(catalogTracker, regionInfo, sn, updateSeqNum);
411 }
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426 private static void updateLocation(final CatalogTracker catalogTracker,
427 HRegionInfo regionInfo, ServerName sn, long openSeqNum)
428 throws IOException {
429 Put put = new Put(regionInfo.getRegionName());
430 addLocation(put, sn, openSeqNum);
431 putToCatalogTable(catalogTracker, put);
432 LOG.info("Updated row " + regionInfo.getRegionNameAsString() +
433 " with server=" + sn);
434 }
435
436
437
438
439
440
441
442 public static void deleteRegion(CatalogTracker catalogTracker,
443 HRegionInfo regionInfo)
444 throws IOException {
445 Delete delete = new Delete(regionInfo.getRegionName());
446 deleteFromMetaTable(catalogTracker, delete);
447 LOG.info("Deleted region " + regionInfo.getRegionNameAsString() + " from META");
448 }
449
450
451
452
453
454
455
456 public static void deleteRegions(CatalogTracker catalogTracker,
457 List<HRegionInfo> regionsInfo) throws IOException {
458 List<Delete> deletes = new ArrayList<Delete>(regionsInfo.size());
459 for (HRegionInfo hri: regionsInfo) {
460 deletes.add(new Delete(hri.getRegionName()));
461 }
462 deleteFromMetaTable(catalogTracker, deletes);
463 LOG.info("Deleted from META, regions: " + regionsInfo);
464 }
465
466
467
468
469
470
471
472
473 public static void mutateRegions(CatalogTracker catalogTracker,
474 final List<HRegionInfo> regionsToRemove, final List<HRegionInfo> regionsToAdd)
475 throws IOException {
476 List<Mutation> mutation = new ArrayList<Mutation>();
477 if (regionsToRemove != null) {
478 for (HRegionInfo hri: regionsToRemove) {
479 mutation.add(new Delete(hri.getRegionName()));
480 }
481 }
482 if (regionsToAdd != null) {
483 for (HRegionInfo hri: regionsToAdd) {
484 mutation.add(makePutFromRegionInfo(hri));
485 }
486 }
487 mutateMetaTable(catalogTracker, mutation);
488 if (regionsToRemove != null && regionsToRemove.size() > 0) {
489 LOG.debug("Deleted from META, regions: " + regionsToRemove);
490 }
491 if (regionsToAdd != null && regionsToAdd.size() > 0) {
492 LOG.debug("Add to META, regions: " + regionsToAdd);
493 }
494 }
495
496
497
498
499
500
501
502
503 public static void deleteDaughtersReferencesInParent(CatalogTracker catalogTracker,
504 final HRegionInfo parent)
505 throws NotAllMetaRegionsOnlineException, IOException {
506 Delete delete = new Delete(parent.getRegionName());
507 delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SPLITA_QUALIFIER);
508 delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SPLITB_QUALIFIER);
509 deleteFromMetaTable(catalogTracker, delete);
510 LOG.info("Deleted daughters references, qualifier=" + Bytes.toStringBinary(HConstants.SPLITA_QUALIFIER) +
511 " and qualifier=" + Bytes.toStringBinary(HConstants.SPLITB_QUALIFIER) +
512 ", from parent " + parent.getRegionNameAsString());
513 }
514
515
516
517
518
519
520
521 public static void deleteMergeQualifiers(CatalogTracker catalogTracker,
522 final HRegionInfo mergedRegion) throws IOException {
523 Delete delete = new Delete(mergedRegion.getRegionName());
524 delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.MERGEA_QUALIFIER);
525 delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.MERGEB_QUALIFIER);
526 deleteFromMetaTable(catalogTracker, delete);
527 LOG.info("Deleted references in merged region "
528 + mergedRegion.getRegionNameAsString() + ", qualifier="
529 + Bytes.toStringBinary(HConstants.MERGEA_QUALIFIER) + " and qualifier="
530 + Bytes.toStringBinary(HConstants.MERGEB_QUALIFIER));
531 }
532
533 private static Put addRegionInfo(final Put p, final HRegionInfo hri)
534 throws IOException {
535 p.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
536 hri.toByteArray());
537 return p;
538 }
539
540 private static Put addLocation(final Put p, final ServerName sn, long openSeqNum) {
541 p.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
542 Bytes.toBytes(sn.getHostAndPort()));
543 p.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
544 Bytes.toBytes(sn.getStartcode()));
545 p.add(HConstants.CATALOG_FAMILY, HConstants.SEQNUM_QUALIFIER,
546 Bytes.toBytes(openSeqNum));
547 return p;
548 }
549 }