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