1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.client;
20
21 import java.io.Closeable;
22 import java.io.IOException;
23 import java.io.InterruptedIOException;
24 import java.net.SocketTimeoutException;
25 import java.util.Arrays;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.concurrent.Callable;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicReference;
31 import java.util.regex.Pattern;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.hadoop.classification.InterfaceAudience;
36 import org.apache.hadoop.classification.InterfaceStability;
37 import org.apache.hadoop.conf.Configuration;
38 import org.apache.hadoop.hbase.Abortable;
39 import org.apache.hadoop.hbase.ClusterStatus;
40 import org.apache.hadoop.hbase.HBaseConfiguration;
41 import org.apache.hadoop.hbase.HColumnDescriptor;
42 import org.apache.hadoop.hbase.HConstants;
43 import org.apache.hadoop.hbase.HRegionInfo;
44 import org.apache.hadoop.hbase.HRegionLocation;
45 import org.apache.hadoop.hbase.HTableDescriptor;
46 import org.apache.hadoop.hbase.ServerName;
47 import org.apache.hadoop.hbase.catalog.CatalogTracker;
48 import org.apache.hadoop.hbase.catalog.MetaReader;
49 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
50 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
51 import org.apache.hadoop.hbase.exceptions.DeserializationException;
52 import org.apache.hadoop.hbase.exceptions.FailedLogCloseException;
53 import org.apache.hadoop.hbase.exceptions.HBaseIOException;
54 import org.apache.hadoop.hbase.exceptions.HBaseSnapshotException;
55 import org.apache.hadoop.hbase.exceptions.MasterNotRunningException;
56 import org.apache.hadoop.hbase.exceptions.NotServingRegionException;
57 import org.apache.hadoop.hbase.exceptions.RegionException;
58 import org.apache.hadoop.hbase.exceptions.RestoreSnapshotException;
59 import org.apache.hadoop.hbase.exceptions.SnapshotCreationException;
60 import org.apache.hadoop.hbase.exceptions.TableExistsException;
61 import org.apache.hadoop.hbase.exceptions.TableNotEnabledException;
62 import org.apache.hadoop.hbase.exceptions.TableNotFoundException;
63 import org.apache.hadoop.hbase.exceptions.UnknownRegionException;
64 import org.apache.hadoop.hbase.exceptions.UnknownSnapshotException;
65 import org.apache.hadoop.hbase.exceptions.ZooKeeperConnectionException;
66 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
67 import org.apache.hadoop.hbase.ipc.MasterCoprocessorRpcChannel;
68 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
69 import org.apache.hadoop.hbase.protobuf.RequestConverter;
70 import org.apache.hadoop.hbase.protobuf.ResponseConverter;
71 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
72 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
73 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
74 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
75 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
76 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse;
77 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse.CompactionState;
78 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRequest;
79 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterResponse;
80 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
81 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
82 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanResponse;
83 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
84 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableSchema;
85 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.AddColumnRequest;
86 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.AssignRegionRequest;
87 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.CreateTableRequest;
88 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DeleteColumnRequest;
89 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DeleteSnapshotRequest;
90 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DeleteTableRequest;
91 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DisableTableRequest;
92 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DispatchMergingRegionsRequest;
93 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.EnableTableRequest;
94 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsRestoreSnapshotDoneRequest;
95 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsRestoreSnapshotDoneResponse;
96 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsSnapshotDoneRequest;
97 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsSnapshotDoneResponse;
98 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ListSnapshotRequest;
99 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ModifyColumnRequest;
100 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ModifyTableRequest;
101 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.MoveRegionRequest;
102 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.RestoreSnapshotRequest;
103 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.RestoreSnapshotResponse;
104 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.SetBalancerRunningRequest;
105 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ShutdownRequest;
106 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.StopMasterRequest;
107 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.TakeSnapshotRequest;
108 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.TakeSnapshotResponse;
109 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.UnassignRegionRequest;
110 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetClusterStatusRequest;
111 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetSchemaAlterStatusRequest;
112 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetSchemaAlterStatusResponse;
113 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetTableDescriptorsRequest;
114 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetTableDescriptorsResponse;
115 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
116 import org.apache.hadoop.hbase.util.Addressing;
117 import org.apache.hadoop.hbase.util.Bytes;
118 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
119 import org.apache.hadoop.hbase.util.Pair;
120 import org.apache.hadoop.ipc.RemoteException;
121 import org.apache.hadoop.util.StringUtils;
122 import org.apache.zookeeper.KeeperException;
123
124 import com.google.protobuf.ByteString;
125 import com.google.protobuf.ServiceException;
126
127
128
129
130
131
132
133
134
135
136 @InterfaceAudience.Public
137 @InterfaceStability.Evolving
138 public class HBaseAdmin implements Abortable, Closeable {
139 private static final Log LOG = LogFactory.getLog(HBaseAdmin.class);
140
141
142
143 private HConnection connection;
144
145 private volatile Configuration conf;
146 private final long pause;
147 private final int numRetries;
148
149
150
151 private final int retryLongerMultiplier;
152 private boolean aborted;
153
154
155
156
157
158
159
160 public HBaseAdmin(Configuration c)
161 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
162
163
164 this(HConnectionManager.getConnection(new Configuration(c)));
165 }
166
167
168
169
170
171
172
173
174
175 public HBaseAdmin(HConnection connection)
176 throws MasterNotRunningException, ZooKeeperConnectionException {
177 this.conf = connection.getConfiguration();
178 this.connection = connection;
179
180 this.pause = this.conf.getLong("hbase.client.pause", 1000);
181 this.numRetries = this.conf.getInt("hbase.client.retries.number", 10);
182 this.retryLongerMultiplier = this.conf.getInt(
183 "hbase.client.retries.longer.multiplier", 10);
184 }
185
186
187
188
189
190
191
192
193 private synchronized CatalogTracker getCatalogTracker()
194 throws ZooKeeperConnectionException, IOException {
195 CatalogTracker ct = null;
196 try {
197 ct = new CatalogTracker(this.conf);
198 ct.start();
199 } catch (InterruptedException e) {
200
201 Thread.currentThread().interrupt();
202 throw new IOException("Interrupted", e);
203 }
204 return ct;
205 }
206
207 private void cleanupCatalogTracker(final CatalogTracker ct) {
208 ct.stop();
209 }
210
211 @Override
212 public void abort(String why, Throwable e) {
213
214 this.aborted = true;
215 throw new RuntimeException(why, e);
216 }
217
218 @Override
219 public boolean isAborted(){
220 return this.aborted;
221 }
222
223
224 public HConnection getConnection() {
225 return connection;
226 }
227
228
229
230
231
232
233 public boolean isMasterRunning()
234 throws MasterNotRunningException, ZooKeeperConnectionException {
235 return connection.isMasterRunning();
236 }
237
238
239
240
241
242
243 public boolean tableExists(final String tableName)
244 throws IOException {
245 boolean b = false;
246 CatalogTracker ct = getCatalogTracker();
247 try {
248 b = MetaReader.tableExists(ct, tableName);
249 } finally {
250 cleanupCatalogTracker(ct);
251 }
252 return b;
253 }
254
255
256
257
258
259
260 public boolean tableExists(final byte [] tableName)
261 throws IOException {
262 return tableExists(Bytes.toString(tableName));
263 }
264
265
266
267
268
269
270
271
272
273
274
275 public HTableDescriptor[] listTables() throws IOException {
276 return this.connection.listTables();
277 }
278
279
280
281
282
283
284
285
286
287 public HTableDescriptor[] listTables(Pattern pattern) throws IOException {
288 List<HTableDescriptor> matched = new LinkedList<HTableDescriptor>();
289 HTableDescriptor[] tables = listTables();
290 for (HTableDescriptor table : tables) {
291 if (pattern.matcher(table.getNameAsString()).matches()) {
292 matched.add(table);
293 }
294 }
295 return matched.toArray(new HTableDescriptor[matched.size()]);
296 }
297
298
299
300
301
302
303
304
305
306 public HTableDescriptor[] listTables(String regex) throws IOException {
307 return listTables(Pattern.compile(regex));
308 }
309
310
311
312
313
314
315
316
317
318 public HTableDescriptor getTableDescriptor(final byte [] tableName)
319 throws TableNotFoundException, IOException {
320 return this.connection.getHTableDescriptor(tableName);
321 }
322
323 private long getPauseTime(int tries) {
324 int triesCount = tries;
325 if (triesCount >= HConstants.RETRY_BACKOFF.length) {
326 triesCount = HConstants.RETRY_BACKOFF.length - 1;
327 }
328 return this.pause * HConstants.RETRY_BACKOFF[triesCount];
329 }
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344 public void createTable(HTableDescriptor desc)
345 throws IOException {
346 createTable(desc, null);
347 }
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 public void createTable(HTableDescriptor desc, byte [] startKey,
374 byte [] endKey, int numRegions)
375 throws IOException {
376 HTableDescriptor.isLegalTableName(desc.getName());
377 if(numRegions < 3) {
378 throw new IllegalArgumentException("Must create at least three regions");
379 } else if(Bytes.compareTo(startKey, endKey) >= 0) {
380 throw new IllegalArgumentException("Start key must be smaller than end key");
381 }
382 if (numRegions == 3) {
383 createTable(desc, new byte[][]{startKey, endKey});
384 return;
385 }
386 byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
387 if(splitKeys == null || splitKeys.length != numRegions - 1) {
388 throw new IllegalArgumentException("Unable to split key range into enough regions");
389 }
390 createTable(desc, splitKeys);
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410 public void createTable(final HTableDescriptor desc, byte [][] splitKeys)
411 throws IOException {
412 HTableDescriptor.isLegalTableName(desc.getName());
413 try {
414 createTableAsync(desc, splitKeys);
415 } catch (SocketTimeoutException ste) {
416 LOG.warn("Creating " + desc.getNameAsString() + " took too long", ste);
417 }
418 int numRegs = splitKeys == null ? 1 : splitKeys.length + 1;
419 int prevRegCount = 0;
420 boolean doneWithMetaScan = false;
421 for (int tries = 0; tries < this.numRetries * this.retryLongerMultiplier;
422 ++tries) {
423 if (!doneWithMetaScan) {
424
425 final AtomicInteger actualRegCount = new AtomicInteger(0);
426 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
427 @Override
428 public boolean processRow(Result rowResult) throws IOException {
429 HRegionInfo info = HRegionInfo.getHRegionInfo(rowResult);
430 if (info == null) {
431 LOG.warn("No serialized HRegionInfo in " + rowResult);
432 return true;
433 }
434 if (!(Bytes.equals(info.getTableName(), desc.getName()))) {
435 return false;
436 }
437 ServerName serverName = HRegionInfo.getServerName(rowResult);
438
439 if (!(info.isOffline() || info.isSplit()) && serverName != null
440 && serverName.getHostAndPort() != null) {
441 actualRegCount.incrementAndGet();
442 }
443 return true;
444 }
445 };
446 MetaScanner.metaScan(conf, visitor, desc.getName());
447 if (actualRegCount.get() != numRegs) {
448 if (tries == this.numRetries * this.retryLongerMultiplier - 1) {
449 throw new RegionOfflineException("Only " + actualRegCount.get() +
450 " of " + numRegs + " regions are online; retries exhausted.");
451 }
452 try {
453 Thread.sleep(getPauseTime(tries));
454 } catch (InterruptedException e) {
455 throw new InterruptedIOException("Interrupted when opening" +
456 " regions; " + actualRegCount.get() + " of " + numRegs +
457 " regions processed so far");
458 }
459 if (actualRegCount.get() > prevRegCount) {
460 prevRegCount = actualRegCount.get();
461 tries = -1;
462 }
463 } else {
464 doneWithMetaScan = true;
465 tries = -1;
466 }
467 } else if (isTableEnabled(desc.getName())) {
468 return;
469 } else {
470 try {
471 Thread.sleep(getPauseTime(tries));
472 } catch (InterruptedException e) {
473 throw new InterruptedIOException("Interrupted when waiting" +
474 " for table to be enabled; meta scan was done");
475 }
476 }
477 }
478 throw new TableNotEnabledException(
479 "Retries exhausted while still waiting for table: "
480 + desc.getNameAsString() + " to be enabled");
481 }
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499 public void createTableAsync(
500 final HTableDescriptor desc, final byte [][] splitKeys)
501 throws IOException {
502 HTableDescriptor.isLegalTableName(desc.getName());
503 if(splitKeys != null && splitKeys.length > 0) {
504 Arrays.sort(splitKeys, Bytes.BYTES_COMPARATOR);
505
506 byte [] lastKey = null;
507 for(byte [] splitKey : splitKeys) {
508 if (Bytes.compareTo(splitKey, HConstants.EMPTY_BYTE_ARRAY) == 0) {
509 throw new IllegalArgumentException(
510 "Empty split key must not be passed in the split keys.");
511 }
512 if(lastKey != null && Bytes.equals(splitKey, lastKey)) {
513 throw new IllegalArgumentException("All split keys must be unique, " +
514 "found duplicate: " + Bytes.toStringBinary(splitKey) +
515 ", " + Bytes.toStringBinary(lastKey));
516 }
517 lastKey = splitKey;
518 }
519 }
520
521 execute(new MasterAdminCallable<Void>() {
522 @Override
523 public Void call() throws ServiceException {
524 CreateTableRequest request = RequestConverter.buildCreateTableRequest(desc, splitKeys);
525 masterAdmin.createTable(null, request);
526 return null;
527 }
528 });
529 }
530
531
532
533
534
535
536
537
538 public void deleteTable(final String tableName) throws IOException {
539 deleteTable(Bytes.toBytes(tableName));
540 }
541
542
543
544
545
546
547
548
549 public void deleteTable(final byte [] tableName) throws IOException {
550 HTableDescriptor.isLegalTableName(tableName);
551 HRegionLocation firstMetaServer = getFirstMetaServerForTable(tableName);
552 boolean tableExists = true;
553
554 execute(new MasterAdminCallable<Void>() {
555 @Override
556 public Void call() throws ServiceException {
557 DeleteTableRequest req = RequestConverter.buildDeleteTableRequest(tableName);
558 masterAdmin.deleteTable(null,req);
559 return null;
560 }
561 });
562
563
564 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
565 try {
566
567 Scan scan = MetaReader.getScanForTableName(tableName);
568 scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
569 ScanRequest request = RequestConverter.buildScanRequest(
570 firstMetaServer.getRegionInfo().getRegionName(), scan, 1, true);
571 Result[] values = null;
572
573 ClientProtocol server = connection.getClient(firstMetaServer.getServerName());
574 try {
575 ScanResponse response = server.scan(null, request);
576 values = ResponseConverter.getResults(response);
577 } catch (ServiceException se) {
578 throw ProtobufUtil.getRemoteException(se);
579 }
580
581
582
583 if (values == null || values.length == 0) {
584 tableExists = false;
585 GetTableDescriptorsResponse htds;
586 MasterMonitorKeepAliveConnection master = connection.getKeepAliveMasterMonitor();
587 try {
588 GetTableDescriptorsRequest req =
589 RequestConverter.buildGetTableDescriptorsRequest(null);
590 htds = master.getTableDescriptors(null, req);
591 } catch (ServiceException se) {
592 throw ProtobufUtil.getRemoteException(se);
593 } finally {
594 master.close();
595 }
596 for (TableSchema ts : htds.getTableSchemaList()) {
597 if (Bytes.equals(tableName, ts.getName().toByteArray())) {
598 tableExists = true;
599 break;
600 }
601 }
602 if (!tableExists) {
603 break;
604 }
605 }
606 } catch (IOException ex) {
607 if(tries == numRetries - 1) {
608 if (ex instanceof RemoteException) {
609 throw ((RemoteException) ex).unwrapRemoteException();
610 }else {
611 throw ex;
612 }
613 }
614 }
615 try {
616 Thread.sleep(getPauseTime(tries));
617 } catch (InterruptedException e) {
618
619 }
620 }
621
622 if (tableExists) {
623 throw new IOException("Retries exhausted, it took too long to wait"+
624 " for the table " + Bytes.toString(tableName) + " to be deleted.");
625 }
626
627 this.connection.clearRegionCache(tableName);
628 LOG.info("Deleted " + Bytes.toString(tableName));
629 }
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644 public HTableDescriptor[] deleteTables(String regex) throws IOException {
645 return deleteTables(Pattern.compile(regex));
646 }
647
648
649
650
651
652
653
654
655
656
657
658
659 public HTableDescriptor[] deleteTables(Pattern pattern) throws IOException {
660 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
661 for (HTableDescriptor table : listTables(pattern)) {
662 try {
663 deleteTable(table.getName());
664 } catch (IOException ex) {
665 LOG.info("Failed to delete table " + table.getNameAsString(), ex);
666 failed.add(table);
667 }
668 }
669 return failed.toArray(new HTableDescriptor[failed.size()]);
670 }
671
672
673 public void enableTable(final String tableName)
674 throws IOException {
675 enableTable(Bytes.toBytes(tableName));
676 }
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691 public void enableTable(final byte [] tableName)
692 throws IOException {
693 enableTableAsync(tableName);
694
695
696 waitUntilTableIsEnabled(tableName);
697
698 LOG.info("Enabled table " + Bytes.toString(tableName));
699 }
700
701
702
703
704
705
706
707
708 private void waitUntilTableIsEnabled(final byte[] tableName) throws IOException {
709 boolean enabled = false;
710 long start = EnvironmentEdgeManager.currentTimeMillis();
711 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
712 enabled = isTableEnabled(tableName) && isTableAvailable(tableName);
713 if (enabled) {
714 break;
715 }
716 long sleep = getPauseTime(tries);
717 if (LOG.isDebugEnabled()) {
718 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
719 "enabled in " + Bytes.toString(tableName));
720 }
721 try {
722 Thread.sleep(sleep);
723 } catch (InterruptedException e) {
724 Thread.currentThread().interrupt();
725
726
727 throw new IOException("Interrupted", e);
728 }
729 }
730 if (!enabled) {
731 long msec = EnvironmentEdgeManager.currentTimeMillis() - start;
732 throw new IOException("Table '" + Bytes.toString(tableName) +
733 "' not yet enabled, after " + msec + "ms.");
734 }
735 }
736
737 public void enableTableAsync(final String tableName)
738 throws IOException {
739 enableTableAsync(Bytes.toBytes(tableName));
740 }
741
742
743
744
745
746
747
748
749
750
751
752 public void enableTableAsync(final byte [] tableName)
753 throws IOException {
754 HTableDescriptor.isLegalTableName(tableName);
755 execute(new MasterAdminCallable<Void>() {
756 @Override
757 public Void call() throws ServiceException {
758 LOG.info("Started enable of " + Bytes.toString(tableName));
759 EnableTableRequest req = RequestConverter.buildEnableTableRequest(tableName);
760 masterAdmin.enableTable(null,req);
761 return null;
762 }
763 });
764 }
765
766
767
768
769
770
771
772
773
774
775
776
777
778 public HTableDescriptor[] enableTables(String regex) throws IOException {
779 return enableTables(Pattern.compile(regex));
780 }
781
782
783
784
785
786
787
788
789
790
791
792 public HTableDescriptor[] enableTables(Pattern pattern) throws IOException {
793 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
794 for (HTableDescriptor table : listTables(pattern)) {
795 if (isTableDisabled(table.getName())) {
796 try {
797 enableTable(table.getName());
798 } catch (IOException ex) {
799 LOG.info("Failed to enable table " + table.getNameAsString(), ex);
800 failed.add(table);
801 }
802 }
803 }
804 return failed.toArray(new HTableDescriptor[failed.size()]);
805 }
806
807 public void disableTableAsync(final String tableName) throws IOException {
808 disableTableAsync(Bytes.toBytes(tableName));
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824 public void disableTableAsync(final byte [] tableName) throws IOException {
825 HTableDescriptor.isLegalTableName(tableName);
826 execute(new MasterAdminCallable<Void>() {
827 @Override
828 public Void call() throws ServiceException {
829 LOG.info("Started disable of " + Bytes.toString(tableName));
830 DisableTableRequest req = RequestConverter.buildDisableTableRequest(tableName);
831 masterAdmin.disableTable(null,req);
832 return null;
833 }
834 });
835 }
836
837 public void disableTable(final String tableName)
838 throws IOException {
839 disableTable(Bytes.toBytes(tableName));
840 }
841
842
843
844
845
846
847
848
849
850
851
852
853 public void disableTable(final byte [] tableName)
854 throws IOException {
855 disableTableAsync(tableName);
856
857 boolean disabled = false;
858 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
859 disabled = isTableDisabled(tableName);
860 if (disabled) {
861 break;
862 }
863 long sleep = getPauseTime(tries);
864 if (LOG.isDebugEnabled()) {
865 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
866 "disabled in " + Bytes.toString(tableName));
867 }
868 try {
869 Thread.sleep(sleep);
870 } catch (InterruptedException e) {
871
872
873 Thread.currentThread().interrupt();
874 throw new IOException("Interrupted", e);
875 }
876 }
877 if (!disabled) {
878 throw new RegionException("Retries exhausted, it took too long to wait"+
879 " for the table " + Bytes.toString(tableName) + " to be disabled.");
880 }
881 LOG.info("Disabled " + Bytes.toString(tableName));
882 }
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897 public HTableDescriptor[] disableTables(String regex) throws IOException {
898 return disableTables(Pattern.compile(regex));
899 }
900
901
902
903
904
905
906
907
908
909
910
911
912 public HTableDescriptor[] disableTables(Pattern pattern) throws IOException {
913 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
914 for (HTableDescriptor table : listTables(pattern)) {
915 if (isTableEnabled(table.getName())) {
916 try {
917 disableTable(table.getName());
918 } catch (IOException ex) {
919 LOG.info("Failed to disable table " + table.getNameAsString(), ex);
920 failed.add(table);
921 }
922 }
923 }
924 return failed.toArray(new HTableDescriptor[failed.size()]);
925 }
926
927
928
929
930
931
932 public boolean isTableEnabled(String tableName) throws IOException {
933 return isTableEnabled(Bytes.toBytes(tableName));
934 }
935
936
937
938
939
940 public boolean isTableEnabled(byte[] tableName) throws IOException {
941 if (!HTableDescriptor.isMetaTable(tableName)) {
942 HTableDescriptor.isLegalTableName(tableName);
943 }
944 return connection.isTableEnabled(tableName);
945 }
946
947
948
949
950
951
952 public boolean isTableDisabled(final String tableName) throws IOException {
953 return isTableDisabled(Bytes.toBytes(tableName));
954 }
955
956
957
958
959
960
961 public boolean isTableDisabled(byte[] tableName) throws IOException {
962 if (!HTableDescriptor.isMetaTable(tableName)) {
963 HTableDescriptor.isLegalTableName(tableName);
964 }
965 return connection.isTableDisabled(tableName);
966 }
967
968
969
970
971
972
973 public boolean isTableAvailable(byte[] tableName) throws IOException {
974 return connection.isTableAvailable(tableName);
975 }
976
977
978
979
980
981
982 public boolean isTableAvailable(String tableName) throws IOException {
983 return connection.isTableAvailable(Bytes.toBytes(tableName));
984 }
985
986
987
988
989
990
991
992
993
994
995
996
997
998 public boolean isTableAvailable(String tableName, byte[][] splitKeys) throws IOException {
999 return connection.isTableAvailable(Bytes.toBytes(tableName), splitKeys);
1000 }
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014 public boolean isTableAvailable(byte[] tableName, byte[][] splitKeys) throws IOException {
1015 return connection.isTableAvailable(tableName, splitKeys);
1016 }
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030 public Pair<Integer, Integer> getAlterStatus(final byte[] tableName)
1031 throws IOException {
1032 HTableDescriptor.isLegalTableName(tableName);
1033 return execute(new MasterMonitorCallable<Pair<Integer, Integer>>() {
1034 @Override
1035 public Pair<Integer, Integer> call() throws ServiceException {
1036 GetSchemaAlterStatusRequest req = RequestConverter
1037 .buildGetSchemaAlterStatusRequest(tableName);
1038 GetSchemaAlterStatusResponse ret = masterMonitor.getSchemaAlterStatus(null, req);
1039 Pair<Integer, Integer> pair = new Pair<Integer, Integer>(Integer.valueOf(ret
1040 .getYetToUpdateRegions()), Integer.valueOf(ret.getTotalRegions()));
1041 return pair;
1042 }
1043 });
1044 }
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054 public void addColumn(final String tableName, HColumnDescriptor column)
1055 throws IOException {
1056 addColumn(Bytes.toBytes(tableName), column);
1057 }
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067 public void addColumn(final byte [] tableName, final HColumnDescriptor column)
1068 throws IOException {
1069 execute(new MasterAdminCallable<Void>() {
1070 @Override
1071 public Void call() throws ServiceException {
1072 AddColumnRequest req = RequestConverter.buildAddColumnRequest(tableName, column);
1073 masterAdmin.addColumn(null,req);
1074 return null;
1075 }
1076 });
1077 }
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087 public void deleteColumn(final String tableName, final String columnName)
1088 throws IOException {
1089 deleteColumn(Bytes.toBytes(tableName), Bytes.toBytes(columnName));
1090 }
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100 public void deleteColumn(final byte [] tableName, final byte [] columnName)
1101 throws IOException {
1102 execute(new MasterAdminCallable<Void>() {
1103 @Override
1104 public Void call() throws ServiceException {
1105 DeleteColumnRequest req = RequestConverter.buildDeleteColumnRequest(tableName, columnName);
1106 masterAdmin.deleteColumn(null,req);
1107 return null;
1108 }
1109 });
1110 }
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120 public void modifyColumn(final String tableName, HColumnDescriptor descriptor)
1121 throws IOException {
1122 modifyColumn(Bytes.toBytes(tableName), descriptor);
1123 }
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 public void modifyColumn(final byte [] tableName, final HColumnDescriptor descriptor)
1136 throws IOException {
1137 execute(new MasterAdminCallable<Void>() {
1138 @Override
1139 public Void call() throws ServiceException {
1140 ModifyColumnRequest req = RequestConverter.buildModifyColumnRequest(tableName, descriptor);
1141 masterAdmin.modifyColumn(null,req);
1142 return null;
1143 }
1144 });
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155 public void closeRegion(final String regionname, final String serverName)
1156 throws IOException {
1157 closeRegion(Bytes.toBytes(regionname), serverName);
1158 }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170 public void closeRegion(final byte [] regionname, final String serverName)
1171 throws IOException {
1172 CatalogTracker ct = getCatalogTracker();
1173 try {
1174 if (serverName != null) {
1175 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1176 if (pair == null || pair.getFirst() == null) {
1177 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1178 } else {
1179 closeRegion(new ServerName(serverName), pair.getFirst());
1180 }
1181 } else {
1182 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1183 if (pair == null) {
1184 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1185 } else if (pair.getSecond() == null) {
1186 throw new NoServerForRegionException(Bytes.toStringBinary(regionname));
1187 } else {
1188 closeRegion(pair.getSecond(), pair.getFirst());
1189 }
1190 }
1191 } finally {
1192 cleanupCatalogTracker(ct);
1193 }
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217 public boolean closeRegionWithEncodedRegionName(final String encodedRegionName,
1218 final String serverName) throws IOException {
1219 if (null == serverName || ("").equals(serverName.trim())) {
1220 throw new IllegalArgumentException(
1221 "The servername cannot be null or empty.");
1222 }
1223 ServerName sn = new ServerName(serverName);
1224 AdminProtocol admin = this.connection.getAdmin(sn);
1225
1226 CloseRegionRequest request =
1227 RequestConverter.buildCloseRegionRequest(encodedRegionName, false);
1228 try {
1229 CloseRegionResponse response = admin.closeRegion(null, request);
1230 boolean isRegionClosed = response.getClosed();
1231 if (false == isRegionClosed) {
1232 LOG.error("Not able to close the region " + encodedRegionName + ".");
1233 }
1234 return isRegionClosed;
1235 } catch (ServiceException se) {
1236 throw ProtobufUtil.getRemoteException(se);
1237 }
1238 }
1239
1240
1241
1242
1243
1244
1245
1246
1247 public void closeRegion(final ServerName sn, final HRegionInfo hri)
1248 throws IOException {
1249 AdminProtocol admin =
1250 this.connection.getAdmin(sn);
1251
1252 ProtobufUtil.closeRegion(admin, hri.getRegionName(), false);
1253 }
1254
1255
1256
1257
1258 public List<HRegionInfo> getOnlineRegions(
1259 final ServerName sn) throws IOException {
1260 AdminProtocol admin =
1261 this.connection.getAdmin(sn);
1262 return ProtobufUtil.getOnlineRegions(admin);
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 public void flush(final String tableNameOrRegionName)
1274 throws IOException, InterruptedException {
1275 flush(Bytes.toBytes(tableNameOrRegionName));
1276 }
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286 public void flush(final byte [] tableNameOrRegionName)
1287 throws IOException, InterruptedException {
1288 CatalogTracker ct = getCatalogTracker();
1289 try {
1290 Pair<HRegionInfo, ServerName> regionServerPair
1291 = getRegion(tableNameOrRegionName, ct);
1292 if (regionServerPair != null) {
1293 if (regionServerPair.getSecond() == null) {
1294 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1295 } else {
1296 flush(regionServerPair.getSecond(), regionServerPair.getFirst());
1297 }
1298 } else {
1299 final String tableName = tableNameString(tableNameOrRegionName, ct);
1300 List<Pair<HRegionInfo, ServerName>> pairs =
1301 MetaReader.getTableRegionsAndLocations(ct,
1302 tableName);
1303 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1304 if (pair.getFirst().isOffline()) continue;
1305 if (pair.getSecond() == null) continue;
1306 try {
1307 flush(pair.getSecond(), pair.getFirst());
1308 } catch (NotServingRegionException e) {
1309 if (LOG.isDebugEnabled()) {
1310 LOG.debug("Trying to flush " + pair.getFirst() + ": " +
1311 StringUtils.stringifyException(e));
1312 }
1313 }
1314 }
1315 }
1316 } finally {
1317 cleanupCatalogTracker(ct);
1318 }
1319 }
1320
1321 private void flush(final ServerName sn, final HRegionInfo hri)
1322 throws IOException {
1323 AdminProtocol admin =
1324 this.connection.getAdmin(sn);
1325 FlushRegionRequest request =
1326 RequestConverter.buildFlushRegionRequest(hri.getRegionName());
1327 try {
1328 admin.flushRegion(null, request);
1329 } catch (ServiceException se) {
1330 throw ProtobufUtil.getRemoteException(se);
1331 }
1332 }
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342 public void compact(final String tableNameOrRegionName)
1343 throws IOException, InterruptedException {
1344 compact(Bytes.toBytes(tableNameOrRegionName));
1345 }
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355 public void compact(final byte [] tableNameOrRegionName)
1356 throws IOException, InterruptedException {
1357 compact(tableNameOrRegionName, null, false);
1358 }
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369 public void compact(String tableOrRegionName, String columnFamily)
1370 throws IOException, InterruptedException {
1371 compact(Bytes.toBytes(tableOrRegionName), Bytes.toBytes(columnFamily));
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383 public void compact(final byte [] tableNameOrRegionName, final byte[] columnFamily)
1384 throws IOException, InterruptedException {
1385 compact(tableNameOrRegionName, columnFamily, false);
1386 }
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396 public void majorCompact(final String tableNameOrRegionName)
1397 throws IOException, InterruptedException {
1398 majorCompact(Bytes.toBytes(tableNameOrRegionName));
1399 }
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409 public void majorCompact(final byte [] tableNameOrRegionName)
1410 throws IOException, InterruptedException {
1411 compact(tableNameOrRegionName, null, true);
1412 }
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423 public void majorCompact(final String tableNameOrRegionName,
1424 final String columnFamily) throws IOException, InterruptedException {
1425 majorCompact(Bytes.toBytes(tableNameOrRegionName),
1426 Bytes.toBytes(columnFamily));
1427 }
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438 public void majorCompact(final byte [] tableNameOrRegionName,
1439 final byte[] columnFamily) throws IOException, InterruptedException {
1440 compact(tableNameOrRegionName, columnFamily, true);
1441 }
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453 private void compact(final byte [] tableNameOrRegionName,
1454 final byte[] columnFamily,final boolean major)
1455 throws IOException, InterruptedException {
1456 CatalogTracker ct = getCatalogTracker();
1457 try {
1458 Pair<HRegionInfo, ServerName> regionServerPair
1459 = getRegion(tableNameOrRegionName, ct);
1460 if (regionServerPair != null) {
1461 if (regionServerPair.getSecond() == null) {
1462 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1463 } else {
1464 compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major, columnFamily);
1465 }
1466 } else {
1467 final String tableName = tableNameString(tableNameOrRegionName, ct);
1468 List<Pair<HRegionInfo, ServerName>> pairs =
1469 MetaReader.getTableRegionsAndLocations(ct,
1470 tableName);
1471 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1472 if (pair.getFirst().isOffline()) continue;
1473 if (pair.getSecond() == null) continue;
1474 try {
1475 compact(pair.getSecond(), pair.getFirst(), major, columnFamily);
1476 } catch (NotServingRegionException e) {
1477 if (LOG.isDebugEnabled()) {
1478 LOG.debug("Trying to" + (major ? " major" : "") + " compact " +
1479 pair.getFirst() + ": " +
1480 StringUtils.stringifyException(e));
1481 }
1482 }
1483 }
1484 }
1485 } finally {
1486 cleanupCatalogTracker(ct);
1487 }
1488 }
1489
1490 private void compact(final ServerName sn, final HRegionInfo hri,
1491 final boolean major, final byte [] family)
1492 throws IOException {
1493 AdminProtocol admin =
1494 this.connection.getAdmin(sn);
1495 CompactRegionRequest request =
1496 RequestConverter.buildCompactRegionRequest(hri.getRegionName(), major, family);
1497 try {
1498 admin.compactRegion(null, request);
1499 } catch (ServiceException se) {
1500 throw ProtobufUtil.getRemoteException(se);
1501 }
1502 }
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519 public void move(final byte [] encodedRegionName, final byte [] destServerName)
1520 throws HBaseIOException, MasterNotRunningException, ZooKeeperConnectionException {
1521 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin();
1522 try {
1523 MoveRegionRequest request = RequestConverter.buildMoveRegionRequest(encodedRegionName, destServerName);
1524 master.moveRegion(null,request);
1525 } catch (ServiceException se) {
1526 IOException ioe = ProtobufUtil.getRemoteException(se);
1527 if (ioe instanceof HBaseIOException) {
1528 throw (HBaseIOException)ioe;
1529 }
1530 LOG.error("Unexpected exception: " + se + " from calling HMaster.moveRegion");
1531 } catch (DeserializationException de) {
1532 LOG.error("Could not parse destination server name: " + de);
1533 }
1534 finally {
1535 master.close();
1536 }
1537 }
1538
1539
1540
1541
1542
1543
1544
1545
1546 public void assign(final byte[] regionName) throws MasterNotRunningException,
1547 ZooKeeperConnectionException, IOException {
1548 execute(new MasterAdminCallable<Void>() {
1549 @Override
1550 public Void call() throws ServiceException {
1551 AssignRegionRequest request = RequestConverter.buildAssignRegionRequest(regionName);
1552 masterAdmin.assignRegion(null,request);
1553 return null;
1554 }
1555 });
1556 }
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572 public void unassign(final byte [] regionName, final boolean force)
1573 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
1574 execute(new MasterAdminCallable<Void>() {
1575 @Override
1576 public Void call() throws ServiceException {
1577 UnassignRegionRequest request =
1578 RequestConverter.buildUnassignRegionRequest(regionName, force);
1579 masterAdmin.unassignRegion(null,request);
1580 return null;
1581 }
1582 });
1583 }
1584
1585
1586
1587
1588 public void offline(final byte [] regionName)
1589 throws IOException {
1590 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin();
1591 try {
1592 master.offlineRegion(null,RequestConverter.buildOfflineRegionRequest(regionName));
1593 } catch (ServiceException se) {
1594 throw ProtobufUtil.getRemoteException(se);
1595 } finally {
1596 master.close();
1597 }
1598 }
1599
1600
1601
1602
1603
1604
1605
1606 public boolean setBalancerRunning(final boolean on, final boolean synchronous)
1607 throws MasterNotRunningException, ZooKeeperConnectionException {
1608 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin();
1609 try {
1610 SetBalancerRunningRequest req =
1611 RequestConverter.buildSetBalancerRunningRequest(on, synchronous);
1612 return master.setBalancerRunning(null, req).getPrevBalanceValue();
1613 } catch (ServiceException se) {
1614 IOException ioe = ProtobufUtil.getRemoteException(se);
1615 if (ioe instanceof MasterNotRunningException) {
1616 throw (MasterNotRunningException)ioe;
1617 }
1618 if (ioe instanceof ZooKeeperConnectionException) {
1619 throw (ZooKeeperConnectionException)ioe;
1620 }
1621
1622
1623
1624 throw new MasterNotRunningException("Unexpected exception when calling balanceSwitch",se);
1625 } finally {
1626 master.close();
1627 }
1628 }
1629
1630
1631
1632
1633
1634
1635
1636 public boolean balancer()
1637 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException {
1638 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin();
1639 try {
1640 return master.balance(null,RequestConverter.buildBalanceRequest()).getBalancerRan();
1641 } finally {
1642 master.close();
1643 }
1644 }
1645
1646
1647
1648
1649
1650
1651
1652
1653 public boolean enableCatalogJanitor(boolean enable)
1654 throws ServiceException, MasterNotRunningException {
1655 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin();
1656 try {
1657 return master.enableCatalogJanitor(null,
1658 RequestConverter.buildEnableCatalogJanitorRequest(enable)).getPrevValue();
1659 } finally {
1660 master.close();
1661 }
1662 }
1663
1664
1665
1666
1667
1668
1669
1670 public int runCatalogScan() throws ServiceException, MasterNotRunningException {
1671 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin();
1672 try {
1673 return master.runCatalogScan(null,
1674 RequestConverter.buildCatalogScanRequest()).getScanResult();
1675 } finally {
1676 master.close();
1677 }
1678 }
1679
1680
1681
1682
1683
1684
1685 public boolean isCatalogJanitorEnabled() throws ServiceException, MasterNotRunningException {
1686 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin();
1687 try {
1688 return master.isCatalogJanitorEnabled(null,
1689 RequestConverter.buildIsCatalogJanitorEnabledRequest()).getValue();
1690 } finally {
1691 master.close();
1692 }
1693 }
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703 public void mergeRegions(final byte[] encodedNameOfRegionA,
1704 final byte[] encodedNameOfRegionB, final boolean forcible)
1705 throws IOException {
1706 MasterAdminKeepAliveConnection master = connection
1707 .getKeepAliveMasterAdmin();
1708 try {
1709 DispatchMergingRegionsRequest request = RequestConverter
1710 .buildDispatchMergingRegionsRequest(encodedNameOfRegionA,
1711 encodedNameOfRegionB, forcible);
1712 master.dispatchMergingRegions(null, request);
1713 } catch (ServiceException se) {
1714 IOException ioe = ProtobufUtil.getRemoteException(se);
1715 if (ioe instanceof UnknownRegionException) {
1716 throw (UnknownRegionException) ioe;
1717 }
1718 LOG.error("Unexpected exception: " + se
1719 + " from calling HMaster.dispatchMergingRegions");
1720 } catch (DeserializationException de) {
1721 LOG.error("Could not parse destination server name: " + de);
1722 } finally {
1723 master.close();
1724 }
1725 }
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735 public void split(final String tableNameOrRegionName)
1736 throws IOException, InterruptedException {
1737 split(Bytes.toBytes(tableNameOrRegionName));
1738 }
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748 public void split(final byte [] tableNameOrRegionName)
1749 throws IOException, InterruptedException {
1750 split(tableNameOrRegionName, null);
1751 }
1752
1753 public void split(final String tableNameOrRegionName,
1754 final String splitPoint) throws IOException, InterruptedException {
1755 split(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(splitPoint));
1756 }
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767 public void split(final byte [] tableNameOrRegionName,
1768 final byte [] splitPoint) throws IOException, InterruptedException {
1769 CatalogTracker ct = getCatalogTracker();
1770 try {
1771 Pair<HRegionInfo, ServerName> regionServerPair
1772 = getRegion(tableNameOrRegionName, ct);
1773 if (regionServerPair != null) {
1774 if (regionServerPair.getSecond() == null) {
1775 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1776 } else {
1777 split(regionServerPair.getSecond(), regionServerPair.getFirst(), splitPoint);
1778 }
1779 } else {
1780 final String tableName = tableNameString(tableNameOrRegionName, ct);
1781 List<Pair<HRegionInfo, ServerName>> pairs =
1782 MetaReader.getTableRegionsAndLocations(ct,
1783 tableName);
1784 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1785
1786 if (pair.getSecond() == null) continue;
1787 HRegionInfo r = pair.getFirst();
1788
1789 if (r.isSplitParent()) continue;
1790
1791 if (splitPoint != null && !r.containsRow(splitPoint)) continue;
1792
1793 split(pair.getSecond(), pair.getFirst(), splitPoint);
1794 }
1795 }
1796 } finally {
1797 cleanupCatalogTracker(ct);
1798 }
1799 }
1800
1801 private void split(final ServerName sn, final HRegionInfo hri,
1802 byte[] splitPoint) throws IOException {
1803 AdminProtocol admin =
1804 this.connection.getAdmin(sn);
1805 ProtobufUtil.split(admin, hri, splitPoint);
1806 }
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817 public void modifyTable(final byte [] tableName, final HTableDescriptor htd)
1818 throws IOException {
1819 execute(new MasterAdminCallable<Void>() {
1820 @Override
1821 public Void call() throws ServiceException {
1822 ModifyTableRequest request = RequestConverter.buildModifyTableRequest(tableName, htd);
1823 masterAdmin.modifyTable(null, request);
1824 return null;
1825 }
1826 });
1827 }
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838 Pair<HRegionInfo, ServerName> getRegion(final byte[] tableNameOrRegionName,
1839 final CatalogTracker ct) throws IOException {
1840 if (tableNameOrRegionName == null) {
1841 throw new IllegalArgumentException("Pass a table name or region name");
1842 }
1843 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, tableNameOrRegionName);
1844 if (pair == null) {
1845 final AtomicReference<Pair<HRegionInfo, ServerName>> result =
1846 new AtomicReference<Pair<HRegionInfo, ServerName>>(null);
1847 final String encodedName = Bytes.toString(tableNameOrRegionName);
1848 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
1849 @Override
1850 public boolean processRow(Result data) throws IOException {
1851 HRegionInfo info = HRegionInfo.getHRegionInfo(data);
1852 if (info == null) {
1853 LOG.warn("No serialized HRegionInfo in " + data);
1854 return true;
1855 }
1856 if (!encodedName.equals(info.getEncodedName())) return true;
1857 ServerName sn = HRegionInfo.getServerName(data);
1858 result.set(new Pair<HRegionInfo, ServerName>(info, sn));
1859 return false;
1860 }
1861 };
1862
1863 MetaScanner.metaScan(conf, visitor);
1864 pair = result.get();
1865 }
1866 return pair;
1867 }
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 private String tableNameString(final byte[] tableNameBytes, CatalogTracker ct)
1879 throws IOException {
1880 String tableNameString = Bytes.toString(tableNameBytes);
1881 if (!MetaReader.tableExists(ct, tableNameString)) {
1882 throw new TableNotFoundException(tableNameString);
1883 }
1884 return tableNameString;
1885 }
1886
1887
1888
1889
1890
1891 public synchronized void shutdown() throws IOException {
1892 execute(new MasterAdminCallable<Void>() {
1893 @Override
1894 public Void call() throws ServiceException {
1895 masterAdmin.shutdown(null,ShutdownRequest.newBuilder().build());
1896 return null;
1897 }
1898 });
1899 }
1900
1901
1902
1903
1904
1905
1906
1907 public synchronized void stopMaster() throws IOException {
1908 execute(new MasterAdminCallable<Void>() {
1909 @Override
1910 public Void call() throws ServiceException {
1911 masterAdmin.stopMaster(null,StopMasterRequest.newBuilder().build());
1912 return null;
1913 }
1914 });
1915 }
1916
1917
1918
1919
1920
1921
1922
1923 public synchronized void stopRegionServer(final String hostnamePort)
1924 throws IOException {
1925 String hostname = Addressing.parseHostname(hostnamePort);
1926 int port = Addressing.parsePort(hostnamePort);
1927 AdminProtocol admin =
1928 this.connection.getAdmin(new ServerName(hostname, port, 0));
1929 StopServerRequest request = RequestConverter.buildStopServerRequest(
1930 "Called by admin client " + this.connection.toString());
1931 try {
1932 admin.stopServer(null, request);
1933 } catch (ServiceException se) {
1934 throw ProtobufUtil.getRemoteException(se);
1935 }
1936 }
1937
1938
1939
1940
1941
1942
1943 public ClusterStatus getClusterStatus() throws IOException {
1944 return execute(new MasterMonitorCallable<ClusterStatus>() {
1945 @Override
1946 public ClusterStatus call() throws ServiceException {
1947 GetClusterStatusRequest req = RequestConverter.buildGetClusterStatusRequest();
1948 return ClusterStatus.convert(masterMonitor.getClusterStatus(null,req).getClusterStatus());
1949 }
1950 });
1951 }
1952
1953 private HRegionLocation getFirstMetaServerForTable(final byte [] tableName)
1954 throws IOException {
1955 return connection.locateRegion(HConstants.META_TABLE_NAME,
1956 HRegionInfo.createRegionName(tableName, null, HConstants.NINES, false));
1957 }
1958
1959
1960
1961
1962 public Configuration getConfiguration() {
1963 return this.conf;
1964 }
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974 public static void checkHBaseAvailable(Configuration conf)
1975 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException, IOException {
1976 Configuration copyOfConf = HBaseConfiguration.create(conf);
1977
1978
1979 copyOfConf.setInt("hbase.client.retries.number", 1);
1980 copyOfConf.setInt("zookeeper.recovery.retry", 0);
1981
1982 HConnectionManager.HConnectionImplementation connection
1983 = (HConnectionManager.HConnectionImplementation)
1984 HConnectionManager.getConnection(copyOfConf);
1985
1986 try {
1987
1988
1989
1990 ZooKeeperKeepAliveConnection zkw = null;
1991 try {
1992 zkw = connection.getKeepAliveZooKeeperWatcher();
1993 zkw.getRecoverableZooKeeper().getZooKeeper().exists(
1994 zkw.baseZNode, false);
1995
1996 } catch (IOException e) {
1997 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
1998 } catch (InterruptedException e) {
1999 Thread.currentThread().interrupt();
2000 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2001 } catch (KeeperException e) {
2002 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2003 } finally {
2004 if (zkw != null) {
2005 zkw.close();
2006 }
2007 }
2008
2009
2010 connection.isMasterRunning();
2011
2012 } finally {
2013 connection.close();
2014 }
2015 }
2016
2017
2018
2019
2020
2021
2022
2023
2024 public List<HRegionInfo> getTableRegions(final byte[] tableName)
2025 throws IOException {
2026 CatalogTracker ct = getCatalogTracker();
2027 List<HRegionInfo> Regions = null;
2028 try {
2029 Regions = MetaReader.getTableRegions(ct, tableName, true);
2030 } finally {
2031 cleanupCatalogTracker(ct);
2032 }
2033 return Regions;
2034 }
2035
2036 @Override
2037 public void close() throws IOException {
2038 if (this.connection != null) {
2039 this.connection.close();
2040 }
2041 }
2042
2043
2044
2045
2046
2047
2048
2049 public HTableDescriptor[] getTableDescriptors(List<String> tableNames)
2050 throws IOException {
2051 return this.connection.getHTableDescriptors(tableNames);
2052 }
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067 public synchronized byte[][] rollHLogWriter(String serverName)
2068 throws IOException, FailedLogCloseException {
2069 ServerName sn = new ServerName(serverName);
2070 AdminProtocol admin = this.connection.getAdmin(sn);
2071 RollWALWriterRequest request = RequestConverter.buildRollWALWriterRequest();
2072 try {
2073 RollWALWriterResponse response = admin.rollWALWriter(null, request);
2074 int regionCount = response.getRegionToFlushCount();
2075 byte[][] regionsToFlush = new byte[regionCount][];
2076 for (int i = 0; i < regionCount; i++) {
2077 ByteString region = response.getRegionToFlush(i);
2078 regionsToFlush[i] = region.toByteArray();
2079 }
2080 return regionsToFlush;
2081 } catch (ServiceException se) {
2082 throw ProtobufUtil.getRemoteException(se);
2083 }
2084 }
2085
2086 public String[] getMasterCoprocessors() {
2087 try {
2088 return getClusterStatus().getMasterCoprocessors();
2089 } catch (IOException e) {
2090 LOG.error("Could not getClusterStatus()",e);
2091 return null;
2092 }
2093 }
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104 public CompactionState getCompactionState(final String tableNameOrRegionName)
2105 throws IOException, InterruptedException {
2106 return getCompactionState(Bytes.toBytes(tableNameOrRegionName));
2107 }
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118 public CompactionState getCompactionState(final byte [] tableNameOrRegionName)
2119 throws IOException, InterruptedException {
2120 CompactionState state = CompactionState.NONE;
2121 CatalogTracker ct = getCatalogTracker();
2122 try {
2123 Pair<HRegionInfo, ServerName> regionServerPair
2124 = getRegion(tableNameOrRegionName, ct);
2125 if (regionServerPair != null) {
2126 if (regionServerPair.getSecond() == null) {
2127 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
2128 } else {
2129 ServerName sn = regionServerPair.getSecond();
2130 AdminProtocol admin =
2131 this.connection.getAdmin(sn);
2132 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
2133 regionServerPair.getFirst().getRegionName(), true);
2134 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
2135 return response.getCompactionState();
2136 }
2137 } else {
2138 final String tableName = tableNameString(tableNameOrRegionName, ct);
2139 List<Pair<HRegionInfo, ServerName>> pairs =
2140 MetaReader.getTableRegionsAndLocations(ct, tableName);
2141 for (Pair<HRegionInfo, ServerName> pair: pairs) {
2142 if (pair.getFirst().isOffline()) continue;
2143 if (pair.getSecond() == null) continue;
2144 try {
2145 ServerName sn = pair.getSecond();
2146 AdminProtocol admin =
2147 this.connection.getAdmin(sn);
2148 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
2149 pair.getFirst().getRegionName(), true);
2150 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
2151 switch (response.getCompactionState()) {
2152 case MAJOR_AND_MINOR:
2153 return CompactionState.MAJOR_AND_MINOR;
2154 case MAJOR:
2155 if (state == CompactionState.MINOR) {
2156 return CompactionState.MAJOR_AND_MINOR;
2157 }
2158 state = CompactionState.MAJOR;
2159 break;
2160 case MINOR:
2161 if (state == CompactionState.MAJOR) {
2162 return CompactionState.MAJOR_AND_MINOR;
2163 }
2164 state = CompactionState.MINOR;
2165 break;
2166 case NONE:
2167 default:
2168 }
2169 } catch (NotServingRegionException e) {
2170 if (LOG.isDebugEnabled()) {
2171 LOG.debug("Trying to get compaction state of " +
2172 pair.getFirst() + ": " +
2173 StringUtils.stringifyException(e));
2174 }
2175 }
2176 }
2177 }
2178 } catch (ServiceException se) {
2179 throw ProtobufUtil.getRemoteException(se);
2180 } finally {
2181 cleanupCatalogTracker(ct);
2182 }
2183 return state;
2184 }
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202 public void snapshot(final String snapshotName, final String tableName) throws IOException,
2203 SnapshotCreationException, IllegalArgumentException {
2204 snapshot(snapshotName, tableName, SnapshotDescription.Type.FLUSH);
2205 }
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222 public void snapshot(final byte[] snapshotName, final byte[] tableName) throws IOException,
2223 SnapshotCreationException, IllegalArgumentException {
2224 snapshot(Bytes.toString(snapshotName), Bytes.toString(tableName));
2225 }
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245 public void snapshot(final String snapshotName, final String tableName,
2246 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2247 IllegalArgumentException {
2248 SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
2249 builder.setTable(tableName);
2250 builder.setName(snapshotName);
2251 builder.setType(type);
2252 snapshot(builder.build());
2253 }
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276 public void snapshot(SnapshotDescription snapshot) throws IOException, SnapshotCreationException,
2277 IllegalArgumentException {
2278
2279 TakeSnapshotResponse response = takeSnapshotAsync(snapshot);
2280 final IsSnapshotDoneRequest request = IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot)
2281 .build();
2282 IsSnapshotDoneResponse done = null;
2283 long start = EnvironmentEdgeManager.currentTimeMillis();
2284 long max = response.getExpectedTimeout();
2285 long maxPauseTime = max / this.numRetries;
2286 int tries = 0;
2287 LOG.debug("Waiting a max of " + max + " ms for snapshot '" +
2288 ClientSnapshotDescriptionUtils.toString(snapshot) + "'' to complete. (max " +
2289 maxPauseTime + " ms per retry)");
2290 while (tries == 0
2291 || ((EnvironmentEdgeManager.currentTimeMillis() - start) < max && !done.getDone())) {
2292 try {
2293
2294 long sleep = getPauseTime(tries++);
2295 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
2296 LOG.debug("(#" + tries + ") Sleeping: " + sleep +
2297 "ms while waiting for snapshot completion.");
2298 Thread.sleep(sleep);
2299
2300 } catch (InterruptedException e) {
2301 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " to complete");
2302 Thread.currentThread().interrupt();
2303 }
2304 LOG.debug("Getting current status of snapshot from master...");
2305 done = execute(new MasterAdminCallable<IsSnapshotDoneResponse>() {
2306 @Override
2307 public IsSnapshotDoneResponse call() throws ServiceException {
2308 return masterAdmin.isSnapshotDone(null, request);
2309 }
2310 });
2311 };
2312 if (!done.getDone()) {
2313 throw new SnapshotCreationException("Snapshot '" + snapshot.getName()
2314 + "' wasn't completed in expectedTime:" + max + " ms", snapshot);
2315 }
2316 }
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328 public TakeSnapshotResponse takeSnapshotAsync(SnapshotDescription snapshot) throws IOException,
2329 SnapshotCreationException {
2330 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
2331 final TakeSnapshotRequest request = TakeSnapshotRequest.newBuilder().setSnapshot(snapshot)
2332 .build();
2333
2334 return execute(new MasterAdminCallable<TakeSnapshotResponse>() {
2335 @Override
2336 public TakeSnapshotResponse call() throws ServiceException {
2337 return masterAdmin.snapshot(null, request);
2338 }
2339 });
2340 }
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362 public boolean isSnapshotFinished(final SnapshotDescription snapshot)
2363 throws IOException, HBaseSnapshotException, UnknownSnapshotException {
2364
2365 return execute(new MasterAdminCallable<IsSnapshotDoneResponse>() {
2366 @Override
2367 public IsSnapshotDoneResponse call() throws ServiceException {
2368 return masterAdmin.isSnapshotDone(null,
2369 IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot).build());
2370 }
2371 }).getDone();
2372 }
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384 public void restoreSnapshot(final byte[] snapshotName)
2385 throws IOException, RestoreSnapshotException {
2386 restoreSnapshot(Bytes.toString(snapshotName));
2387 }
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399 public void restoreSnapshot(final String snapshotName)
2400 throws IOException, RestoreSnapshotException {
2401 String rollbackSnapshot = snapshotName + "-" + EnvironmentEdgeManager.currentTimeMillis();
2402
2403 String tableName = null;
2404 for (SnapshotDescription snapshotInfo: listSnapshots()) {
2405 if (snapshotInfo.getName().equals(snapshotName)) {
2406 tableName = snapshotInfo.getTable();
2407 break;
2408 }
2409 }
2410
2411 if (tableName == null) {
2412 throw new RestoreSnapshotException(
2413 "Unable to find the table name for snapshot=" + snapshotName);
2414 }
2415
2416
2417 snapshot(rollbackSnapshot, tableName);
2418
2419
2420 try {
2421 internalRestoreSnapshot(snapshotName, tableName);
2422 } catch (IOException e) {
2423
2424 try {
2425 String msg = "Restore snapshot=" + snapshotName +
2426 " failed. Rollback to snapshot=" + rollbackSnapshot + " succeeded.";
2427 LOG.error(msg, e);
2428 internalRestoreSnapshot(rollbackSnapshot, tableName);
2429 throw new RestoreSnapshotException(msg, e);
2430 } catch (IOException ex) {
2431 String msg = "Failed to restore and rollback to snapshot=" + rollbackSnapshot;
2432 LOG.error(msg, ex);
2433 throw new RestoreSnapshotException(msg, ex);
2434 }
2435 }
2436 }
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448 public void cloneSnapshot(final byte[] snapshotName, final byte[] tableName)
2449 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2450 cloneSnapshot(Bytes.toString(snapshotName), Bytes.toString(tableName));
2451 }
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463 public void cloneSnapshot(final String snapshotName, final String tableName)
2464 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2465 if (tableExists(tableName)) {
2466 throw new TableExistsException("Table '" + tableName + " already exists");
2467 }
2468 internalRestoreSnapshot(snapshotName, tableName);
2469 waitUntilTableIsEnabled(Bytes.toBytes(tableName));
2470 }
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482 private void internalRestoreSnapshot(final String snapshotName, final String tableName)
2483 throws IOException, RestoreSnapshotException {
2484 SnapshotDescription snapshot = SnapshotDescription.newBuilder()
2485 .setName(snapshotName).setTable(tableName).build();
2486
2487
2488 internalRestoreSnapshotAsync(snapshot);
2489
2490 final IsRestoreSnapshotDoneRequest request = IsRestoreSnapshotDoneRequest.newBuilder()
2491 .setSnapshot(snapshot).build();
2492 IsRestoreSnapshotDoneResponse done = IsRestoreSnapshotDoneResponse.newBuilder().buildPartial();
2493 final long maxPauseTime = 5000;
2494 int tries = 0;
2495 while (!done.getDone()) {
2496 try {
2497
2498 long sleep = getPauseTime(tries++);
2499 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
2500 LOG.debug(tries + ") Sleeping: " + sleep + " ms while we wait for snapshot restore to complete.");
2501 Thread.sleep(sleep);
2502 } catch (InterruptedException e) {
2503 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " restore to complete");
2504 Thread.currentThread().interrupt();
2505 }
2506 LOG.debug("Getting current status of snapshot restore from master...");
2507 done = execute(new MasterAdminCallable<IsRestoreSnapshotDoneResponse>() {
2508 @Override
2509 public IsRestoreSnapshotDoneResponse call() throws ServiceException {
2510 return masterAdmin.isRestoreSnapshotDone(null, request);
2511 }
2512 });
2513 }
2514 if (!done.getDone()) {
2515 throw new RestoreSnapshotException("Snapshot '" + snapshot.getName() + "' wasn't restored.");
2516 }
2517 }
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529 private RestoreSnapshotResponse internalRestoreSnapshotAsync(final SnapshotDescription snapshot)
2530 throws IOException, RestoreSnapshotException {
2531 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
2532
2533 final RestoreSnapshotRequest request = RestoreSnapshotRequest.newBuilder().setSnapshot(snapshot)
2534 .build();
2535
2536
2537 return execute(new MasterAdminCallable<RestoreSnapshotResponse>() {
2538 @Override
2539 public RestoreSnapshotResponse call() throws ServiceException {
2540 return masterAdmin.restoreSnapshot(null, request);
2541 }
2542 });
2543 }
2544
2545
2546
2547
2548
2549
2550 public List<SnapshotDescription> listSnapshots() throws IOException {
2551 return execute(new MasterAdminCallable<List<SnapshotDescription>>() {
2552 @Override
2553 public List<SnapshotDescription> call() throws ServiceException {
2554 return masterAdmin.getCompletedSnapshots(null, ListSnapshotRequest.newBuilder().build())
2555 .getSnapshotsList();
2556 }
2557 });
2558 }
2559
2560
2561
2562
2563
2564
2565 public void deleteSnapshot(final byte[] snapshotName) throws IOException {
2566 deleteSnapshot(Bytes.toString(snapshotName));
2567 }
2568
2569
2570
2571
2572
2573
2574 public void deleteSnapshot(final String snapshotName) throws IOException {
2575
2576 HTableDescriptor.isLegalTableName(Bytes.toBytes(snapshotName));
2577
2578 execute(new MasterAdminCallable<Void>() {
2579 @Override
2580 public Void call() throws ServiceException {
2581 masterAdmin.deleteSnapshot(
2582 null,
2583 DeleteSnapshotRequest.newBuilder()
2584 .setSnapshot(SnapshotDescription.newBuilder().setName(snapshotName).build()).build());
2585 return null;
2586 }
2587 });
2588 }
2589
2590
2591
2592
2593 private abstract static class MasterAdminCallable<V> implements Callable<V>{
2594 protected MasterAdminKeepAliveConnection masterAdmin;
2595 }
2596
2597
2598
2599
2600 private abstract static class MasterMonitorCallable<V> implements Callable<V> {
2601 protected MasterMonitorKeepAliveConnection masterMonitor;
2602 }
2603
2604
2605
2606
2607
2608
2609 private <V> V execute(MasterAdminCallable<V> function) throws IOException {
2610 function.masterAdmin = connection.getKeepAliveMasterAdmin();
2611 try {
2612 return executeCallable(function);
2613 } finally {
2614 function.masterAdmin.close();
2615 }
2616 }
2617
2618
2619
2620
2621
2622
2623 private <V> V execute(MasterMonitorCallable<V> function) throws IOException {
2624 function.masterMonitor = connection.getKeepAliveMasterMonitor();
2625 try {
2626 return executeCallable(function);
2627 } finally {
2628 function.masterMonitor.close();
2629 }
2630 }
2631
2632
2633
2634
2635 private <V> V executeCallable(Callable<V> function) throws IOException {
2636 try {
2637 return function.call();
2638 } catch (RemoteException re) {
2639 throw re.unwrapRemoteException();
2640 } catch (IOException e) {
2641 throw e;
2642 } catch (ServiceException se) {
2643 throw ProtobufUtil.getRemoteException(se);
2644 } catch (Exception e) {
2645
2646 throw new IOException("Unexpected exception when calling master", e);
2647 }
2648 }
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671 public CoprocessorRpcChannel coprocessorService() {
2672 return new MasterCoprocessorRpcChannel(connection);
2673 }
2674 }