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.HBaseIOException;
42 import org.apache.hadoop.hbase.HColumnDescriptor;
43 import org.apache.hadoop.hbase.HConstants;
44 import org.apache.hadoop.hbase.HRegionInfo;
45 import org.apache.hadoop.hbase.HRegionLocation;
46 import org.apache.hadoop.hbase.HTableDescriptor;
47 import org.apache.hadoop.hbase.ServerName;
48 import org.apache.hadoop.hbase.catalog.CatalogTracker;
49 import org.apache.hadoop.hbase.catalog.MetaReader;
50 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
51 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
52 import org.apache.hadoop.hbase.exceptions.DeserializationException;
53 import org.apache.hadoop.hbase.exceptions.FailedLogCloseException;
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.AdminService;
72 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
73 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
74 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
75 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
76 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
77 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse;
78 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse.CompactionState;
79 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRequest;
80 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterResponse;
81 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
82 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ClientService;
83 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
84 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanResponse;
85 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
86 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableSchema;
87 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.AddColumnRequest;
88 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.AssignRegionRequest;
89 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.CreateTableRequest;
90 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DeleteColumnRequest;
91 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DeleteSnapshotRequest;
92 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DeleteTableRequest;
93 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DisableTableRequest;
94 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.DispatchMergingRegionsRequest;
95 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.EnableTableRequest;
96 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsRestoreSnapshotDoneRequest;
97 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsRestoreSnapshotDoneResponse;
98 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsSnapshotDoneRequest;
99 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.IsSnapshotDoneResponse;
100 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ListSnapshotRequest;
101 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ModifyColumnRequest;
102 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ModifyTableRequest;
103 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.MoveRegionRequest;
104 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.RestoreSnapshotRequest;
105 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.RestoreSnapshotResponse;
106 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.SetBalancerRunningRequest;
107 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.ShutdownRequest;
108 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.StopMasterRequest;
109 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.TakeSnapshotRequest;
110 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.TakeSnapshotResponse;
111 import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.UnassignRegionRequest;
112 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetClusterStatusRequest;
113 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetSchemaAlterStatusRequest;
114 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetSchemaAlterStatusResponse;
115 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetTableDescriptorsRequest;
116 import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetTableDescriptorsResponse;
117 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
118 import org.apache.hadoop.hbase.util.Addressing;
119 import org.apache.hadoop.hbase.util.Bytes;
120 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
121 import org.apache.hadoop.hbase.util.Pair;
122 import org.apache.hadoop.ipc.RemoteException;
123 import org.apache.hadoop.util.StringUtils;
124 import org.apache.zookeeper.KeeperException;
125
126 import com.google.protobuf.ByteString;
127 import com.google.protobuf.ServiceException;
128
129
130
131
132
133
134
135
136
137
138 @InterfaceAudience.Public
139 @InterfaceStability.Evolving
140 public class HBaseAdmin implements Abortable, Closeable {
141 private static final Log LOG = LogFactory.getLog(HBaseAdmin.class);
142
143
144
145 private HConnection connection;
146
147 private volatile Configuration conf;
148 private final long pause;
149 private final int numRetries;
150
151
152
153 private final int retryLongerMultiplier;
154 private boolean aborted;
155
156
157
158
159
160
161
162 public HBaseAdmin(Configuration c)
163 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
164
165
166 this(HConnectionManager.getConnection(new Configuration(c)));
167 }
168
169
170
171
172
173
174
175
176
177 public HBaseAdmin(HConnection connection)
178 throws MasterNotRunningException, ZooKeeperConnectionException {
179 this.conf = connection.getConfiguration();
180 this.connection = connection;
181
182 this.pause = this.conf.getLong("hbase.client.pause", 1000);
183 this.numRetries = this.conf.getInt("hbase.client.retries.number", 10);
184 this.retryLongerMultiplier = this.conf.getInt(
185 "hbase.client.retries.longer.multiplier", 10);
186 }
187
188
189
190
191
192
193
194
195 private synchronized CatalogTracker getCatalogTracker()
196 throws ZooKeeperConnectionException, IOException {
197 CatalogTracker ct = null;
198 try {
199 ct = new CatalogTracker(this.conf);
200 ct.start();
201 } catch (InterruptedException e) {
202
203 Thread.currentThread().interrupt();
204 throw new IOException("Interrupted", e);
205 }
206 return ct;
207 }
208
209 private void cleanupCatalogTracker(final CatalogTracker ct) {
210 ct.stop();
211 }
212
213 @Override
214 public void abort(String why, Throwable e) {
215
216 this.aborted = true;
217 throw new RuntimeException(why, e);
218 }
219
220 @Override
221 public boolean isAborted(){
222 return this.aborted;
223 }
224
225
226 public HConnection getConnection() {
227 return connection;
228 }
229
230
231
232
233
234
235 public boolean isMasterRunning()
236 throws MasterNotRunningException, ZooKeeperConnectionException {
237 return connection.isMasterRunning();
238 }
239
240
241
242
243
244
245 public boolean tableExists(final String tableName)
246 throws IOException {
247 boolean b = false;
248 CatalogTracker ct = getCatalogTracker();
249 try {
250 b = MetaReader.tableExists(ct, tableName);
251 } finally {
252 cleanupCatalogTracker(ct);
253 }
254 return b;
255 }
256
257
258
259
260
261
262 public boolean tableExists(final byte [] tableName)
263 throws IOException {
264 return tableExists(Bytes.toString(tableName));
265 }
266
267
268
269
270
271
272
273
274
275
276
277 public HTableDescriptor[] listTables() throws IOException {
278 return this.connection.listTables();
279 }
280
281
282
283
284
285
286
287
288
289 public HTableDescriptor[] listTables(Pattern pattern) throws IOException {
290 List<HTableDescriptor> matched = new LinkedList<HTableDescriptor>();
291 HTableDescriptor[] tables = listTables();
292 for (HTableDescriptor table : tables) {
293 if (pattern.matcher(table.getNameAsString()).matches()) {
294 matched.add(table);
295 }
296 }
297 return matched.toArray(new HTableDescriptor[matched.size()]);
298 }
299
300
301
302
303
304
305
306
307
308 public HTableDescriptor[] listTables(String regex) throws IOException {
309 return listTables(Pattern.compile(regex));
310 }
311
312
313
314
315
316
317
318
319
320 public HTableDescriptor getTableDescriptor(final byte [] tableName)
321 throws TableNotFoundException, IOException {
322 return this.connection.getHTableDescriptor(tableName);
323 }
324
325 private long getPauseTime(int tries) {
326 int triesCount = tries;
327 if (triesCount >= HConstants.RETRY_BACKOFF.length) {
328 triesCount = HConstants.RETRY_BACKOFF.length - 1;
329 }
330 return this.pause * HConstants.RETRY_BACKOFF[triesCount];
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 public void createTable(HTableDescriptor desc)
347 throws IOException {
348 createTable(desc, null);
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
374
375 public void createTable(HTableDescriptor desc, byte [] startKey,
376 byte [] endKey, int numRegions)
377 throws IOException {
378 HTableDescriptor.isLegalTableName(desc.getName());
379 if(numRegions < 3) {
380 throw new IllegalArgumentException("Must create at least three regions");
381 } else if(Bytes.compareTo(startKey, endKey) >= 0) {
382 throw new IllegalArgumentException("Start key must be smaller than end key");
383 }
384 if (numRegions == 3) {
385 createTable(desc, new byte[][]{startKey, endKey});
386 return;
387 }
388 byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
389 if(splitKeys == null || splitKeys.length != numRegions - 1) {
390 throw new IllegalArgumentException("Unable to split key range into enough regions");
391 }
392 createTable(desc, splitKeys);
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412 public void createTable(final HTableDescriptor desc, byte [][] splitKeys)
413 throws IOException {
414 HTableDescriptor.isLegalTableName(desc.getName());
415 try {
416 createTableAsync(desc, splitKeys);
417 } catch (SocketTimeoutException ste) {
418 LOG.warn("Creating " + desc.getNameAsString() + " took too long", ste);
419 }
420 int numRegs = splitKeys == null ? 1 : splitKeys.length + 1;
421 int prevRegCount = 0;
422 boolean doneWithMetaScan = false;
423 for (int tries = 0; tries < this.numRetries * this.retryLongerMultiplier;
424 ++tries) {
425 if (!doneWithMetaScan) {
426
427 final AtomicInteger actualRegCount = new AtomicInteger(0);
428 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
429 @Override
430 public boolean processRow(Result rowResult) throws IOException {
431 HRegionInfo info = HRegionInfo.getHRegionInfo(rowResult);
432 if (info == null) {
433 LOG.warn("No serialized HRegionInfo in " + rowResult);
434 return true;
435 }
436 if (!(Bytes.equals(info.getTableName(), desc.getName()))) {
437 return false;
438 }
439 ServerName serverName = HRegionInfo.getServerName(rowResult);
440
441 if (!(info.isOffline() || info.isSplit()) && serverName != null
442 && serverName.getHostAndPort() != null) {
443 actualRegCount.incrementAndGet();
444 }
445 return true;
446 }
447 };
448 MetaScanner.metaScan(conf, visitor, desc.getName());
449 if (actualRegCount.get() != numRegs) {
450 if (tries == this.numRetries * this.retryLongerMultiplier - 1) {
451 throw new RegionOfflineException("Only " + actualRegCount.get() +
452 " of " + numRegs + " regions are online; retries exhausted.");
453 }
454 try {
455 Thread.sleep(getPauseTime(tries));
456 } catch (InterruptedException e) {
457 throw new InterruptedIOException("Interrupted when opening" +
458 " regions; " + actualRegCount.get() + " of " + numRegs +
459 " regions processed so far");
460 }
461 if (actualRegCount.get() > prevRegCount) {
462 prevRegCount = actualRegCount.get();
463 tries = -1;
464 }
465 } else {
466 doneWithMetaScan = true;
467 tries = -1;
468 }
469 } else if (isTableEnabled(desc.getName())) {
470 return;
471 } else {
472 try {
473 Thread.sleep(getPauseTime(tries));
474 } catch (InterruptedException e) {
475 throw new InterruptedIOException("Interrupted when waiting" +
476 " for table to be enabled; meta scan was done");
477 }
478 }
479 }
480 throw new TableNotEnabledException(
481 "Retries exhausted while still waiting for table: "
482 + desc.getNameAsString() + " to be enabled");
483 }
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501 public void createTableAsync(
502 final HTableDescriptor desc, final byte [][] splitKeys)
503 throws IOException {
504 HTableDescriptor.isLegalTableName(desc.getName());
505 if(splitKeys != null && splitKeys.length > 0) {
506 Arrays.sort(splitKeys, Bytes.BYTES_COMPARATOR);
507
508 byte [] lastKey = null;
509 for(byte [] splitKey : splitKeys) {
510 if (Bytes.compareTo(splitKey, HConstants.EMPTY_BYTE_ARRAY) == 0) {
511 throw new IllegalArgumentException(
512 "Empty split key must not be passed in the split keys.");
513 }
514 if(lastKey != null && Bytes.equals(splitKey, lastKey)) {
515 throw new IllegalArgumentException("All split keys must be unique, " +
516 "found duplicate: " + Bytes.toStringBinary(splitKey) +
517 ", " + Bytes.toStringBinary(lastKey));
518 }
519 lastKey = splitKey;
520 }
521 }
522
523 execute(new MasterAdminCallable<Void>() {
524 @Override
525 public Void call() throws ServiceException {
526 CreateTableRequest request = RequestConverter.buildCreateTableRequest(desc, splitKeys);
527 masterAdmin.createTable(null, request);
528 return null;
529 }
530 });
531 }
532
533
534
535
536
537
538
539
540 public void deleteTable(final String tableName) throws IOException {
541 deleteTable(Bytes.toBytes(tableName));
542 }
543
544
545
546
547
548
549
550
551 public void deleteTable(final byte [] tableName) throws IOException {
552 HTableDescriptor.isLegalTableName(tableName);
553 HRegionLocation firstMetaServer = getFirstMetaServerForTable(tableName);
554 boolean tableExists = true;
555
556 execute(new MasterAdminCallable<Void>() {
557 @Override
558 public Void call() throws ServiceException {
559 DeleteTableRequest req = RequestConverter.buildDeleteTableRequest(tableName);
560 masterAdmin.deleteTable(null,req);
561 return null;
562 }
563 });
564
565
566 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
567 try {
568
569 Scan scan = MetaReader.getScanForTableName(tableName);
570 scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
571 ScanRequest request = RequestConverter.buildScanRequest(
572 firstMetaServer.getRegionInfo().getRegionName(), scan, 1, true);
573 Result[] values = null;
574
575 ClientService.BlockingInterface server = connection.getClient(firstMetaServer.getServerName());
576 try {
577 ScanResponse response = server.scan(null, request);
578 values = ResponseConverter.getResults(response);
579 } catch (ServiceException se) {
580 throw ProtobufUtil.getRemoteException(se);
581 }
582
583
584
585 if (values == null || values.length == 0) {
586 tableExists = false;
587 GetTableDescriptorsResponse htds;
588 MasterMonitorKeepAliveConnection master = connection.getKeepAliveMasterMonitorService();
589 try {
590 GetTableDescriptorsRequest req =
591 RequestConverter.buildGetTableDescriptorsRequest(null);
592 htds = master.getTableDescriptors(null, req);
593 } catch (ServiceException se) {
594 throw ProtobufUtil.getRemoteException(se);
595 } finally {
596 master.close();
597 }
598 for (TableSchema ts : htds.getTableSchemaList()) {
599 if (Bytes.equals(tableName, ts.getName().toByteArray())) {
600 tableExists = true;
601 break;
602 }
603 }
604 if (!tableExists) {
605 break;
606 }
607 }
608 } catch (IOException ex) {
609 if(tries == numRetries - 1) {
610 if (ex instanceof RemoteException) {
611 throw ((RemoteException) ex).unwrapRemoteException();
612 } else {
613 throw ex;
614 }
615 }
616 }
617 try {
618 Thread.sleep(getPauseTime(tries));
619 } catch (InterruptedException e) {
620
621 }
622 }
623
624 if (tableExists) {
625 throw new IOException("Retries exhausted, it took too long to wait"+
626 " for the table " + Bytes.toString(tableName) + " to be deleted.");
627 }
628
629 this.connection.clearRegionCache(tableName);
630 LOG.info("Deleted " + Bytes.toString(tableName));
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646 public HTableDescriptor[] deleteTables(String regex) throws IOException {
647 return deleteTables(Pattern.compile(regex));
648 }
649
650
651
652
653
654
655
656
657
658
659
660
661 public HTableDescriptor[] deleteTables(Pattern pattern) throws IOException {
662 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
663 for (HTableDescriptor table : listTables(pattern)) {
664 try {
665 deleteTable(table.getName());
666 } catch (IOException ex) {
667 LOG.info("Failed to delete table " + table.getNameAsString(), ex);
668 failed.add(table);
669 }
670 }
671 return failed.toArray(new HTableDescriptor[failed.size()]);
672 }
673
674
675 public void enableTable(final String tableName)
676 throws IOException {
677 enableTable(Bytes.toBytes(tableName));
678 }
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693 public void enableTable(final byte [] tableName)
694 throws IOException {
695 enableTableAsync(tableName);
696
697
698 waitUntilTableIsEnabled(tableName);
699
700 LOG.info("Enabled table " + Bytes.toString(tableName));
701 }
702
703
704
705
706
707
708
709
710 private void waitUntilTableIsEnabled(final byte[] tableName) throws IOException {
711 boolean enabled = false;
712 long start = EnvironmentEdgeManager.currentTimeMillis();
713 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
714 enabled = isTableEnabled(tableName) && isTableAvailable(tableName);
715 if (enabled) {
716 break;
717 }
718 long sleep = getPauseTime(tries);
719 if (LOG.isDebugEnabled()) {
720 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
721 "enabled in " + Bytes.toString(tableName));
722 }
723 try {
724 Thread.sleep(sleep);
725 } catch (InterruptedException e) {
726 Thread.currentThread().interrupt();
727
728
729 throw new IOException("Interrupted", e);
730 }
731 }
732 if (!enabled) {
733 long msec = EnvironmentEdgeManager.currentTimeMillis() - start;
734 throw new IOException("Table '" + Bytes.toString(tableName) +
735 "' not yet enabled, after " + msec + "ms.");
736 }
737 }
738
739 public void enableTableAsync(final String tableName)
740 throws IOException {
741 enableTableAsync(Bytes.toBytes(tableName));
742 }
743
744
745
746
747
748
749
750
751
752
753
754 public void enableTableAsync(final byte [] tableName)
755 throws IOException {
756 HTableDescriptor.isLegalTableName(tableName);
757 execute(new MasterAdminCallable<Void>() {
758 @Override
759 public Void call() throws ServiceException {
760 LOG.info("Started enable of " + Bytes.toString(tableName));
761 EnableTableRequest req = RequestConverter.buildEnableTableRequest(tableName);
762 masterAdmin.enableTable(null,req);
763 return null;
764 }
765 });
766 }
767
768
769
770
771
772
773
774
775
776
777
778
779
780 public HTableDescriptor[] enableTables(String regex) throws IOException {
781 return enableTables(Pattern.compile(regex));
782 }
783
784
785
786
787
788
789
790
791
792
793
794 public HTableDescriptor[] enableTables(Pattern pattern) throws IOException {
795 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
796 for (HTableDescriptor table : listTables(pattern)) {
797 if (isTableDisabled(table.getName())) {
798 try {
799 enableTable(table.getName());
800 } catch (IOException ex) {
801 LOG.info("Failed to enable table " + table.getNameAsString(), ex);
802 failed.add(table);
803 }
804 }
805 }
806 return failed.toArray(new HTableDescriptor[failed.size()]);
807 }
808
809 public void disableTableAsync(final String tableName) throws IOException {
810 disableTableAsync(Bytes.toBytes(tableName));
811 }
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826 public void disableTableAsync(final byte [] tableName) throws IOException {
827 HTableDescriptor.isLegalTableName(tableName);
828 execute(new MasterAdminCallable<Void>() {
829 @Override
830 public Void call() throws ServiceException {
831 LOG.info("Started disable of " + Bytes.toString(tableName));
832 DisableTableRequest req = RequestConverter.buildDisableTableRequest(tableName);
833 masterAdmin.disableTable(null,req);
834 return null;
835 }
836 });
837 }
838
839 public void disableTable(final String tableName)
840 throws IOException {
841 disableTable(Bytes.toBytes(tableName));
842 }
843
844
845
846
847
848
849
850
851
852
853
854
855 public void disableTable(final byte [] tableName)
856 throws IOException {
857 disableTableAsync(tableName);
858
859 boolean disabled = false;
860 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
861 disabled = isTableDisabled(tableName);
862 if (disabled) {
863 break;
864 }
865 long sleep = getPauseTime(tries);
866 if (LOG.isDebugEnabled()) {
867 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
868 "disabled in " + Bytes.toString(tableName));
869 }
870 try {
871 Thread.sleep(sleep);
872 } catch (InterruptedException e) {
873
874
875 Thread.currentThread().interrupt();
876 throw new IOException("Interrupted", e);
877 }
878 }
879 if (!disabled) {
880 throw new RegionException("Retries exhausted, it took too long to wait"+
881 " for the table " + Bytes.toString(tableName) + " to be disabled.");
882 }
883 LOG.info("Disabled " + Bytes.toString(tableName));
884 }
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899 public HTableDescriptor[] disableTables(String regex) throws IOException {
900 return disableTables(Pattern.compile(regex));
901 }
902
903
904
905
906
907
908
909
910
911
912
913
914 public HTableDescriptor[] disableTables(Pattern pattern) throws IOException {
915 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
916 for (HTableDescriptor table : listTables(pattern)) {
917 if (isTableEnabled(table.getName())) {
918 try {
919 disableTable(table.getName());
920 } catch (IOException ex) {
921 LOG.info("Failed to disable table " + table.getNameAsString(), ex);
922 failed.add(table);
923 }
924 }
925 }
926 return failed.toArray(new HTableDescriptor[failed.size()]);
927 }
928
929
930
931
932
933
934 public boolean isTableEnabled(String tableName) throws IOException {
935 return isTableEnabled(Bytes.toBytes(tableName));
936 }
937
938
939
940
941
942 public boolean isTableEnabled(byte[] tableName) throws IOException {
943 if (!HTableDescriptor.isMetaTable(tableName)) {
944 HTableDescriptor.isLegalTableName(tableName);
945 }
946 return connection.isTableEnabled(tableName);
947 }
948
949
950
951
952
953
954 public boolean isTableDisabled(final String tableName) throws IOException {
955 return isTableDisabled(Bytes.toBytes(tableName));
956 }
957
958
959
960
961
962
963 public boolean isTableDisabled(byte[] tableName) throws IOException {
964 if (!HTableDescriptor.isMetaTable(tableName)) {
965 HTableDescriptor.isLegalTableName(tableName);
966 }
967 return connection.isTableDisabled(tableName);
968 }
969
970
971
972
973
974
975 public boolean isTableAvailable(byte[] tableName) throws IOException {
976 return connection.isTableAvailable(tableName);
977 }
978
979
980
981
982
983
984 public boolean isTableAvailable(String tableName) throws IOException {
985 return connection.isTableAvailable(Bytes.toBytes(tableName));
986 }
987
988
989
990
991
992
993
994
995
996
997
998
999
1000 public boolean isTableAvailable(String tableName, byte[][] splitKeys) throws IOException {
1001 return connection.isTableAvailable(Bytes.toBytes(tableName), splitKeys);
1002 }
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 public boolean isTableAvailable(byte[] tableName, byte[][] splitKeys) throws IOException {
1017 return connection.isTableAvailable(tableName, splitKeys);
1018 }
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032 public Pair<Integer, Integer> getAlterStatus(final byte[] tableName)
1033 throws IOException {
1034 HTableDescriptor.isLegalTableName(tableName);
1035 return execute(new MasterMonitorCallable<Pair<Integer, Integer>>() {
1036 @Override
1037 public Pair<Integer, Integer> call() throws ServiceException {
1038 GetSchemaAlterStatusRequest req = RequestConverter
1039 .buildGetSchemaAlterStatusRequest(tableName);
1040 GetSchemaAlterStatusResponse ret = masterMonitor.getSchemaAlterStatus(null, req);
1041 Pair<Integer, Integer> pair = new Pair<Integer, Integer>(Integer.valueOf(ret
1042 .getYetToUpdateRegions()), Integer.valueOf(ret.getTotalRegions()));
1043 return pair;
1044 }
1045 });
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 public void addColumn(final String tableName, HColumnDescriptor column)
1057 throws IOException {
1058 addColumn(Bytes.toBytes(tableName), column);
1059 }
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 public void addColumn(final byte [] tableName, final HColumnDescriptor column)
1070 throws IOException {
1071 execute(new MasterAdminCallable<Void>() {
1072 @Override
1073 public Void call() throws ServiceException {
1074 AddColumnRequest req = RequestConverter.buildAddColumnRequest(tableName, column);
1075 masterAdmin.addColumn(null,req);
1076 return null;
1077 }
1078 });
1079 }
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 public void deleteColumn(final String tableName, final String columnName)
1090 throws IOException {
1091 deleteColumn(Bytes.toBytes(tableName), Bytes.toBytes(columnName));
1092 }
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102 public void deleteColumn(final byte [] tableName, final byte [] columnName)
1103 throws IOException {
1104 execute(new MasterAdminCallable<Void>() {
1105 @Override
1106 public Void call() throws ServiceException {
1107 DeleteColumnRequest req = RequestConverter.buildDeleteColumnRequest(tableName, columnName);
1108 masterAdmin.deleteColumn(null,req);
1109 return null;
1110 }
1111 });
1112 }
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122 public void modifyColumn(final String tableName, HColumnDescriptor descriptor)
1123 throws IOException {
1124 modifyColumn(Bytes.toBytes(tableName), descriptor);
1125 }
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137 public void modifyColumn(final byte [] tableName, final HColumnDescriptor descriptor)
1138 throws IOException {
1139 execute(new MasterAdminCallable<Void>() {
1140 @Override
1141 public Void call() throws ServiceException {
1142 ModifyColumnRequest req = RequestConverter.buildModifyColumnRequest(tableName, descriptor);
1143 masterAdmin.modifyColumn(null,req);
1144 return null;
1145 }
1146 });
1147 }
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157 public void closeRegion(final String regionname, final String serverName)
1158 throws IOException {
1159 closeRegion(Bytes.toBytes(regionname), serverName);
1160 }
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 public void closeRegion(final byte [] regionname, final String serverName)
1173 throws IOException {
1174 CatalogTracker ct = getCatalogTracker();
1175 try {
1176 if (serverName != null) {
1177 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1178 if (pair == null || pair.getFirst() == null) {
1179 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1180 } else {
1181 closeRegion(new ServerName(serverName), pair.getFirst());
1182 }
1183 } else {
1184 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1185 if (pair == null) {
1186 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1187 } else if (pair.getSecond() == null) {
1188 throw new NoServerForRegionException(Bytes.toStringBinary(regionname));
1189 } else {
1190 closeRegion(pair.getSecond(), pair.getFirst());
1191 }
1192 }
1193 } finally {
1194 cleanupCatalogTracker(ct);
1195 }
1196 }
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219 public boolean closeRegionWithEncodedRegionName(final String encodedRegionName,
1220 final String serverName) throws IOException {
1221 if (null == serverName || ("").equals(serverName.trim())) {
1222 throw new IllegalArgumentException(
1223 "The servername cannot be null or empty.");
1224 }
1225 ServerName sn = new ServerName(serverName);
1226 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1227
1228 CloseRegionRequest request =
1229 RequestConverter.buildCloseRegionRequest(encodedRegionName, false);
1230 try {
1231 CloseRegionResponse response = admin.closeRegion(null, request);
1232 boolean isRegionClosed = response.getClosed();
1233 if (false == isRegionClosed) {
1234 LOG.error("Not able to close the region " + encodedRegionName + ".");
1235 }
1236 return isRegionClosed;
1237 } catch (ServiceException se) {
1238 throw ProtobufUtil.getRemoteException(se);
1239 }
1240 }
1241
1242
1243
1244
1245
1246
1247
1248
1249 public void closeRegion(final ServerName sn, final HRegionInfo hri)
1250 throws IOException {
1251 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1252
1253 ProtobufUtil.closeRegion(admin, hri.getRegionName(), false);
1254 }
1255
1256
1257
1258
1259 public List<HRegionInfo> getOnlineRegions(
1260 final ServerName sn) throws IOException {
1261 AdminService.BlockingInterface admin = 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 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1324 FlushRegionRequest request =
1325 RequestConverter.buildFlushRegionRequest(hri.getRegionName());
1326 try {
1327 admin.flushRegion(null, request);
1328 } catch (ServiceException se) {
1329 throw ProtobufUtil.getRemoteException(se);
1330 }
1331 }
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341 public void compact(final String tableNameOrRegionName)
1342 throws IOException, InterruptedException {
1343 compact(Bytes.toBytes(tableNameOrRegionName));
1344 }
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354 public void compact(final byte [] tableNameOrRegionName)
1355 throws IOException, InterruptedException {
1356 compact(tableNameOrRegionName, null, false);
1357 }
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368 public void compact(String tableOrRegionName, String columnFamily)
1369 throws IOException, InterruptedException {
1370 compact(Bytes.toBytes(tableOrRegionName), Bytes.toBytes(columnFamily));
1371 }
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382 public void compact(final byte [] tableNameOrRegionName, final byte[] columnFamily)
1383 throws IOException, InterruptedException {
1384 compact(tableNameOrRegionName, columnFamily, false);
1385 }
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395 public void majorCompact(final String tableNameOrRegionName)
1396 throws IOException, InterruptedException {
1397 majorCompact(Bytes.toBytes(tableNameOrRegionName));
1398 }
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408 public void majorCompact(final byte [] tableNameOrRegionName)
1409 throws IOException, InterruptedException {
1410 compact(tableNameOrRegionName, null, true);
1411 }
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422 public void majorCompact(final String tableNameOrRegionName,
1423 final String columnFamily) throws IOException, InterruptedException {
1424 majorCompact(Bytes.toBytes(tableNameOrRegionName),
1425 Bytes.toBytes(columnFamily));
1426 }
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437 public void majorCompact(final byte [] tableNameOrRegionName,
1438 final byte[] columnFamily) throws IOException, InterruptedException {
1439 compact(tableNameOrRegionName, columnFamily, true);
1440 }
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452 private void compact(final byte [] tableNameOrRegionName,
1453 final byte[] columnFamily,final boolean major)
1454 throws IOException, InterruptedException {
1455 CatalogTracker ct = getCatalogTracker();
1456 try {
1457 Pair<HRegionInfo, ServerName> regionServerPair
1458 = getRegion(tableNameOrRegionName, ct);
1459 if (regionServerPair != null) {
1460 if (regionServerPair.getSecond() == null) {
1461 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1462 } else {
1463 compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major, columnFamily);
1464 }
1465 } else {
1466 final String tableName = tableNameString(tableNameOrRegionName, ct);
1467 List<Pair<HRegionInfo, ServerName>> pairs =
1468 MetaReader.getTableRegionsAndLocations(ct,
1469 tableName);
1470 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1471 if (pair.getFirst().isOffline()) continue;
1472 if (pair.getSecond() == null) continue;
1473 try {
1474 compact(pair.getSecond(), pair.getFirst(), major, columnFamily);
1475 } catch (NotServingRegionException e) {
1476 if (LOG.isDebugEnabled()) {
1477 LOG.debug("Trying to" + (major ? " major" : "") + " compact " +
1478 pair.getFirst() + ": " +
1479 StringUtils.stringifyException(e));
1480 }
1481 }
1482 }
1483 }
1484 } finally {
1485 cleanupCatalogTracker(ct);
1486 }
1487 }
1488
1489 private void compact(final ServerName sn, final HRegionInfo hri,
1490 final boolean major, final byte [] family)
1491 throws IOException {
1492 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1493 CompactRegionRequest request =
1494 RequestConverter.buildCompactRegionRequest(hri.getRegionName(), major, family);
1495 try {
1496 admin.compactRegion(null, request);
1497 } catch (ServiceException se) {
1498 throw ProtobufUtil.getRemoteException(se);
1499 }
1500 }
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517 public void move(final byte [] encodedRegionName, final byte [] destServerName)
1518 throws HBaseIOException, MasterNotRunningException, ZooKeeperConnectionException {
1519 MasterAdminKeepAliveConnection stub = connection.getKeepAliveMasterAdminService();
1520 try {
1521 MoveRegionRequest request =
1522 RequestConverter.buildMoveRegionRequest(encodedRegionName, destServerName);
1523 stub.moveRegion(null,request);
1524 } catch (ServiceException se) {
1525 IOException ioe = ProtobufUtil.getRemoteException(se);
1526 if (ioe instanceof HBaseIOException) {
1527 throw (HBaseIOException)ioe;
1528 }
1529 LOG.error("Unexpected exception: " + se + " from calling HMaster.moveRegion");
1530 } catch (DeserializationException de) {
1531 LOG.error("Could not parse destination server name: " + de);
1532 } finally {
1533 stub.close();
1534 }
1535 }
1536
1537
1538
1539
1540
1541
1542
1543
1544 public void assign(final byte[] regionName) throws MasterNotRunningException,
1545 ZooKeeperConnectionException, IOException {
1546 execute(new MasterAdminCallable<Void>() {
1547 @Override
1548 public Void call() throws ServiceException {
1549 AssignRegionRequest request = RequestConverter.buildAssignRegionRequest(regionName);
1550 masterAdmin.assignRegion(null,request);
1551 return null;
1552 }
1553 });
1554 }
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570 public void unassign(final byte [] regionName, final boolean force)
1571 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
1572 execute(new MasterAdminCallable<Void>() {
1573 @Override
1574 public Void call() throws ServiceException {
1575 UnassignRegionRequest request =
1576 RequestConverter.buildUnassignRegionRequest(regionName, force);
1577 masterAdmin.unassignRegion(null,request);
1578 return null;
1579 }
1580 });
1581 }
1582
1583
1584
1585
1586 public void offline(final byte [] regionName)
1587 throws IOException {
1588 MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdminService();
1589 try {
1590 master.offlineRegion(null,RequestConverter.buildOfflineRegionRequest(regionName));
1591 } catch (ServiceException se) {
1592 throw ProtobufUtil.getRemoteException(se);
1593 } finally {
1594 master.close();
1595 }
1596 }
1597
1598
1599
1600
1601
1602
1603
1604 public boolean setBalancerRunning(final boolean on, final boolean synchronous)
1605 throws MasterNotRunningException, ZooKeeperConnectionException {
1606 MasterAdminKeepAliveConnection stub = connection.getKeepAliveMasterAdminService();
1607 try {
1608 SetBalancerRunningRequest req =
1609 RequestConverter.buildSetBalancerRunningRequest(on, synchronous);
1610 return stub.setBalancerRunning(null, req).getPrevBalanceValue();
1611 } catch (ServiceException se) {
1612 IOException ioe = ProtobufUtil.getRemoteException(se);
1613 if (ioe instanceof MasterNotRunningException) {
1614 throw (MasterNotRunningException)ioe;
1615 }
1616 if (ioe instanceof ZooKeeperConnectionException) {
1617 throw (ZooKeeperConnectionException)ioe;
1618 }
1619
1620
1621
1622 throw new MasterNotRunningException("Unexpected exception when calling balanceSwitch",se);
1623 } finally {
1624 stub.close();
1625 }
1626 }
1627
1628
1629
1630
1631
1632
1633
1634 public boolean balancer()
1635 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException {
1636 MasterAdminKeepAliveConnection stub = connection.getKeepAliveMasterAdminService();
1637 try {
1638 return stub.balance(null,RequestConverter.buildBalanceRequest()).getBalancerRan();
1639 } finally {
1640 stub.close();
1641 }
1642 }
1643
1644
1645
1646
1647
1648
1649
1650
1651 public boolean enableCatalogJanitor(boolean enable)
1652 throws ServiceException, MasterNotRunningException {
1653 MasterAdminKeepAliveConnection stub = connection.getKeepAliveMasterAdminService();
1654 try {
1655 return stub.enableCatalogJanitor(null,
1656 RequestConverter.buildEnableCatalogJanitorRequest(enable)).getPrevValue();
1657 } finally {
1658 stub.close();
1659 }
1660 }
1661
1662
1663
1664
1665
1666
1667
1668 public int runCatalogScan() throws ServiceException, MasterNotRunningException {
1669 MasterAdminKeepAliveConnection stub = connection.getKeepAliveMasterAdminService();
1670 try {
1671 return stub.runCatalogScan(null,
1672 RequestConverter.buildCatalogScanRequest()).getScanResult();
1673 } finally {
1674 stub.close();
1675 }
1676 }
1677
1678
1679
1680
1681
1682
1683 public boolean isCatalogJanitorEnabled() throws ServiceException, MasterNotRunningException {
1684 MasterAdminKeepAliveConnection stub = connection.getKeepAliveMasterAdminService();
1685 try {
1686 return stub.isCatalogJanitorEnabled(null,
1687 RequestConverter.buildIsCatalogJanitorEnabledRequest()).getValue();
1688 } finally {
1689 stub.close();
1690 }
1691 }
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701 public void mergeRegions(final byte[] encodedNameOfRegionA,
1702 final byte[] encodedNameOfRegionB, final boolean forcible)
1703 throws IOException {
1704 MasterAdminKeepAliveConnection master = connection
1705 .getKeepAliveMasterAdminService();
1706 try {
1707 DispatchMergingRegionsRequest request = RequestConverter
1708 .buildDispatchMergingRegionsRequest(encodedNameOfRegionA,
1709 encodedNameOfRegionB, forcible);
1710 master.dispatchMergingRegions(null, request);
1711 } catch (ServiceException se) {
1712 IOException ioe = ProtobufUtil.getRemoteException(se);
1713 if (ioe instanceof UnknownRegionException) {
1714 throw (UnknownRegionException) ioe;
1715 }
1716 LOG.error("Unexpected exception: " + se
1717 + " from calling HMaster.dispatchMergingRegions");
1718 } catch (DeserializationException de) {
1719 LOG.error("Could not parse destination server name: " + de);
1720 } finally {
1721 master.close();
1722 }
1723 }
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733 public void split(final String tableNameOrRegionName)
1734 throws IOException, InterruptedException {
1735 split(Bytes.toBytes(tableNameOrRegionName));
1736 }
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746 public void split(final byte [] tableNameOrRegionName)
1747 throws IOException, InterruptedException {
1748 split(tableNameOrRegionName, null);
1749 }
1750
1751 public void split(final String tableNameOrRegionName,
1752 final String splitPoint) throws IOException, InterruptedException {
1753 split(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(splitPoint));
1754 }
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765 public void split(final byte [] tableNameOrRegionName,
1766 final byte [] splitPoint) throws IOException, InterruptedException {
1767 CatalogTracker ct = getCatalogTracker();
1768 try {
1769 Pair<HRegionInfo, ServerName> regionServerPair
1770 = getRegion(tableNameOrRegionName, ct);
1771 if (regionServerPair != null) {
1772 if (regionServerPair.getSecond() == null) {
1773 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1774 } else {
1775 split(regionServerPair.getSecond(), regionServerPair.getFirst(), splitPoint);
1776 }
1777 } else {
1778 final String tableName = tableNameString(tableNameOrRegionName, ct);
1779 List<Pair<HRegionInfo, ServerName>> pairs =
1780 MetaReader.getTableRegionsAndLocations(ct,
1781 tableName);
1782 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1783
1784 if (pair.getSecond() == null) continue;
1785 HRegionInfo r = pair.getFirst();
1786
1787 if (r.isSplitParent()) continue;
1788
1789 if (splitPoint != null && !r.containsRow(splitPoint)) continue;
1790
1791 split(pair.getSecond(), pair.getFirst(), splitPoint);
1792 }
1793 }
1794 } finally {
1795 cleanupCatalogTracker(ct);
1796 }
1797 }
1798
1799 private void split(final ServerName sn, final HRegionInfo hri,
1800 byte[] splitPoint) throws IOException {
1801 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1802 ProtobufUtil.split(admin, hri, splitPoint);
1803 }
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814 public void modifyTable(final byte [] tableName, final HTableDescriptor htd)
1815 throws IOException {
1816 if (!Bytes.equals(tableName, htd.getName())) {
1817 throw new IllegalArgumentException("the specified table name '" + Bytes.toString(tableName) +
1818 "' doesn't match with the HTD one: " + htd.getNameAsString());
1819 }
1820
1821 execute(new MasterAdminCallable<Void>() {
1822 @Override
1823 public Void call() throws ServiceException {
1824 ModifyTableRequest request = RequestConverter.buildModifyTableRequest(tableName, htd);
1825 masterAdmin.modifyTable(null, request);
1826 return null;
1827 }
1828 });
1829 }
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840 Pair<HRegionInfo, ServerName> getRegion(final byte[] tableNameOrRegionName,
1841 final CatalogTracker ct) throws IOException {
1842 if (tableNameOrRegionName == null) {
1843 throw new IllegalArgumentException("Pass a table name or region name");
1844 }
1845 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, tableNameOrRegionName);
1846 if (pair == null) {
1847 final AtomicReference<Pair<HRegionInfo, ServerName>> result =
1848 new AtomicReference<Pair<HRegionInfo, ServerName>>(null);
1849 final String encodedName = Bytes.toString(tableNameOrRegionName);
1850 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
1851 @Override
1852 public boolean processRow(Result data) throws IOException {
1853 HRegionInfo info = HRegionInfo.getHRegionInfo(data);
1854 if (info == null) {
1855 LOG.warn("No serialized HRegionInfo in " + data);
1856 return true;
1857 }
1858 if (!encodedName.equals(info.getEncodedName())) return true;
1859 ServerName sn = HRegionInfo.getServerName(data);
1860 result.set(new Pair<HRegionInfo, ServerName>(info, sn));
1861 return false;
1862 }
1863 };
1864
1865 MetaScanner.metaScan(conf, visitor);
1866 pair = result.get();
1867 }
1868 return pair;
1869 }
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880 private String tableNameString(final byte[] tableNameBytes, CatalogTracker ct)
1881 throws IOException {
1882 String tableNameString = Bytes.toString(tableNameBytes);
1883 if (!MetaReader.tableExists(ct, tableNameString)) {
1884 throw new TableNotFoundException(tableNameString);
1885 }
1886 return tableNameString;
1887 }
1888
1889
1890
1891
1892
1893 public synchronized void shutdown() throws IOException {
1894 execute(new MasterAdminCallable<Void>() {
1895 @Override
1896 public Void call() throws ServiceException {
1897 masterAdmin.shutdown(null,ShutdownRequest.newBuilder().build());
1898 return null;
1899 }
1900 });
1901 }
1902
1903
1904
1905
1906
1907
1908
1909 public synchronized void stopMaster() throws IOException {
1910 execute(new MasterAdminCallable<Void>() {
1911 @Override
1912 public Void call() throws ServiceException {
1913 masterAdmin.stopMaster(null,StopMasterRequest.newBuilder().build());
1914 return null;
1915 }
1916 });
1917 }
1918
1919
1920
1921
1922
1923
1924
1925 public synchronized void stopRegionServer(final String hostnamePort)
1926 throws IOException {
1927 String hostname = Addressing.parseHostname(hostnamePort);
1928 int port = Addressing.parsePort(hostnamePort);
1929 AdminService.BlockingInterface admin =
1930 this.connection.getAdmin(new ServerName(hostname, port, 0));
1931 StopServerRequest request = RequestConverter.buildStopServerRequest(
1932 "Called by admin client " + this.connection.toString());
1933 try {
1934 admin.stopServer(null, request);
1935 } catch (ServiceException se) {
1936 throw ProtobufUtil.getRemoteException(se);
1937 }
1938 }
1939
1940
1941
1942
1943
1944
1945 public ClusterStatus getClusterStatus() throws IOException {
1946 return execute(new MasterMonitorCallable<ClusterStatus>() {
1947 @Override
1948 public ClusterStatus call() throws ServiceException {
1949 GetClusterStatusRequest req = RequestConverter.buildGetClusterStatusRequest();
1950 return ClusterStatus.convert(masterMonitor.getClusterStatus(null,req).getClusterStatus());
1951 }
1952 });
1953 }
1954
1955 private HRegionLocation getFirstMetaServerForTable(final byte [] tableName)
1956 throws IOException {
1957 return connection.locateRegion(HConstants.META_TABLE_NAME,
1958 HRegionInfo.createRegionName(tableName, null, HConstants.NINES, false));
1959 }
1960
1961
1962
1963
1964 public Configuration getConfiguration() {
1965 return this.conf;
1966 }
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976 public static void checkHBaseAvailable(Configuration conf)
1977 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException, IOException {
1978 Configuration copyOfConf = HBaseConfiguration.create(conf);
1979
1980
1981 copyOfConf.setInt("hbase.client.retries.number", 1);
1982 copyOfConf.setInt("zookeeper.recovery.retry", 0);
1983
1984 HConnectionManager.HConnectionImplementation connection
1985 = (HConnectionManager.HConnectionImplementation)
1986 HConnectionManager.getConnection(copyOfConf);
1987
1988 try {
1989
1990
1991
1992 ZooKeeperKeepAliveConnection zkw = null;
1993 try {
1994 zkw = connection.getKeepAliveZooKeeperWatcher();
1995 zkw.getRecoverableZooKeeper().getZooKeeper().exists(
1996 zkw.baseZNode, false);
1997
1998 } catch (IOException e) {
1999 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2000 } catch (InterruptedException e) {
2001 Thread.currentThread().interrupt();
2002 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2003 } catch (KeeperException e) {
2004 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2005 } finally {
2006 if (zkw != null) {
2007 zkw.close();
2008 }
2009 }
2010
2011
2012 connection.isMasterRunning();
2013
2014 } finally {
2015 connection.close();
2016 }
2017 }
2018
2019
2020
2021
2022
2023
2024
2025
2026 public List<HRegionInfo> getTableRegions(final byte[] tableName)
2027 throws IOException {
2028 CatalogTracker ct = getCatalogTracker();
2029 List<HRegionInfo> Regions = null;
2030 try {
2031 Regions = MetaReader.getTableRegions(ct, tableName, true);
2032 } finally {
2033 cleanupCatalogTracker(ct);
2034 }
2035 return Regions;
2036 }
2037
2038 @Override
2039 public void close() throws IOException {
2040 if (this.connection != null) {
2041 this.connection.close();
2042 }
2043 }
2044
2045
2046
2047
2048
2049
2050
2051 public HTableDescriptor[] getTableDescriptors(List<String> tableNames)
2052 throws IOException {
2053 return this.connection.getHTableDescriptors(tableNames);
2054 }
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069 public synchronized byte[][] rollHLogWriter(String serverName)
2070 throws IOException, FailedLogCloseException {
2071 ServerName sn = new ServerName(serverName);
2072 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2073 RollWALWriterRequest request = RequestConverter.buildRollWALWriterRequest();
2074 try {
2075 RollWALWriterResponse response = admin.rollWALWriter(null, request);
2076 int regionCount = response.getRegionToFlushCount();
2077 byte[][] regionsToFlush = new byte[regionCount][];
2078 for (int i = 0; i < regionCount; i++) {
2079 ByteString region = response.getRegionToFlush(i);
2080 regionsToFlush[i] = region.toByteArray();
2081 }
2082 return regionsToFlush;
2083 } catch (ServiceException se) {
2084 throw ProtobufUtil.getRemoteException(se);
2085 }
2086 }
2087
2088 public String[] getMasterCoprocessors() {
2089 try {
2090 return getClusterStatus().getMasterCoprocessors();
2091 } catch (IOException e) {
2092 LOG.error("Could not getClusterStatus()",e);
2093 return null;
2094 }
2095 }
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106 public CompactionState getCompactionState(final String tableNameOrRegionName)
2107 throws IOException, InterruptedException {
2108 return getCompactionState(Bytes.toBytes(tableNameOrRegionName));
2109 }
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120 public CompactionState getCompactionState(final byte [] tableNameOrRegionName)
2121 throws IOException, InterruptedException {
2122 CompactionState state = CompactionState.NONE;
2123 CatalogTracker ct = getCatalogTracker();
2124 try {
2125 Pair<HRegionInfo, ServerName> regionServerPair
2126 = getRegion(tableNameOrRegionName, ct);
2127 if (regionServerPair != null) {
2128 if (regionServerPair.getSecond() == null) {
2129 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
2130 } else {
2131 ServerName sn = regionServerPair.getSecond();
2132 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2133 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
2134 regionServerPair.getFirst().getRegionName(), true);
2135 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
2136 return response.getCompactionState();
2137 }
2138 } else {
2139 final String tableName = tableNameString(tableNameOrRegionName, ct);
2140 List<Pair<HRegionInfo, ServerName>> pairs =
2141 MetaReader.getTableRegionsAndLocations(ct, tableName);
2142 for (Pair<HRegionInfo, ServerName> pair: pairs) {
2143 if (pair.getFirst().isOffline()) continue;
2144 if (pair.getSecond() == null) continue;
2145 try {
2146 ServerName sn = pair.getSecond();
2147 AdminService.BlockingInterface admin = 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
2566
2567 public List<SnapshotDescription> listSnapshots(String regex) throws IOException {
2568 return listSnapshots(Pattern.compile(regex));
2569 }
2570
2571
2572
2573
2574
2575
2576
2577
2578 public List<SnapshotDescription> listSnapshots(Pattern pattern) throws IOException {
2579 List<SnapshotDescription> matched = new LinkedList<SnapshotDescription>();
2580 List<SnapshotDescription> snapshots = listSnapshots();
2581 for (SnapshotDescription snapshot : snapshots) {
2582 if (pattern.matcher(snapshot.getName()).matches()) {
2583 matched.add(snapshot);
2584 }
2585 }
2586 return matched;
2587 }
2588
2589
2590
2591
2592
2593
2594 public void deleteSnapshot(final byte[] snapshotName) throws IOException {
2595 deleteSnapshot(Bytes.toString(snapshotName));
2596 }
2597
2598
2599
2600
2601
2602
2603 public void deleteSnapshot(final String snapshotName) throws IOException {
2604
2605 HTableDescriptor.isLegalTableName(Bytes.toBytes(snapshotName));
2606
2607 execute(new MasterAdminCallable<Void>() {
2608 @Override
2609 public Void call() throws ServiceException {
2610 masterAdmin.deleteSnapshot(
2611 null,
2612 DeleteSnapshotRequest.newBuilder()
2613 .setSnapshot(SnapshotDescription.newBuilder().setName(snapshotName).build()).build());
2614 return null;
2615 }
2616 });
2617 }
2618
2619
2620
2621
2622
2623
2624 public void deleteSnapshots(final String regex) throws IOException {
2625 deleteSnapshots(Pattern.compile(regex));
2626 }
2627
2628
2629
2630
2631
2632
2633 public void deleteSnapshots(final Pattern pattern) throws IOException {
2634 List<SnapshotDescription> snapshots = listSnapshots(pattern);
2635 for (final SnapshotDescription snapshot : snapshots) {
2636
2637 execute(new MasterAdminCallable<Void>() {
2638 @Override
2639 public Void call() throws ServiceException {
2640 masterAdmin.deleteSnapshot(
2641 null,
2642 DeleteSnapshotRequest.newBuilder().setSnapshot(snapshot).build());
2643 return null;
2644 }
2645 });
2646 }
2647 }
2648
2649
2650
2651
2652 private abstract static class MasterAdminCallable<V> implements Callable<V>{
2653 protected MasterAdminKeepAliveConnection masterAdmin;
2654 }
2655
2656
2657
2658
2659 private abstract static class MasterMonitorCallable<V> implements Callable<V> {
2660 protected MasterMonitorKeepAliveConnection masterMonitor;
2661 }
2662
2663
2664
2665
2666
2667
2668 private <V> V execute(MasterAdminCallable<V> function) throws IOException {
2669 function.masterAdmin = connection.getKeepAliveMasterAdminService();
2670 try {
2671 return executeCallable(function);
2672 } finally {
2673 function.masterAdmin.close();
2674 }
2675 }
2676
2677
2678
2679
2680
2681
2682 private <V> V execute(MasterMonitorCallable<V> function) throws IOException {
2683 function.masterMonitor = connection.getKeepAliveMasterMonitorService();
2684 try {
2685 return executeCallable(function);
2686 } finally {
2687 function.masterMonitor.close();
2688 }
2689 }
2690
2691
2692
2693
2694 private <V> V executeCallable(Callable<V> function) throws IOException {
2695 try {
2696 return function.call();
2697 } catch (RemoteException re) {
2698 throw re.unwrapRemoteException();
2699 } catch (IOException e) {
2700 throw e;
2701 } catch (ServiceException se) {
2702 throw ProtobufUtil.getRemoteException(se);
2703 } catch (Exception e) {
2704
2705 throw new IOException("Unexpected exception when calling master", e);
2706 }
2707 }
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730 public CoprocessorRpcChannel coprocessorService() {
2731 return new MasterCoprocessorRpcChannel(connection);
2732 }
2733 }