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.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.MasterNotRunningException;
48 import org.apache.hadoop.hbase.NamespaceDescriptor;
49 import org.apache.hadoop.hbase.NotServingRegionException;
50 import org.apache.hadoop.hbase.RegionException;
51 import org.apache.hadoop.hbase.ServerName;
52 import org.apache.hadoop.hbase.TableExistsException;
53 import org.apache.hadoop.hbase.TableName;
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.exceptions.MergeRegionException;
65 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
66 import org.apache.hadoop.hbase.ipc.MasterCoprocessorRpcChannel;
67 import org.apache.hadoop.hbase.ipc.PayloadCarryingRpcController;
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;
86 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
87 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableSchema;
88 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AddColumnRequest;
89 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
90 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateNamespaceRequest;
91 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
92 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteColumnRequest;
93 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteNamespaceRequest;
94 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteSnapshotRequest;
95 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableRequest;
96 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableRequest;
97 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
98 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableRequest;
99 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetClusterStatusRequest;
100 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetCompletedSnapshotsRequest;
101 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest;
102 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
103 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse;
104 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
105 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
106 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneRequest;
107 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneResponse;
108 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
109 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
110 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
111 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceRequest;
112 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableNamesByNamespaceRequest;
113 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnRequest;
114 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyNamespaceRequest;
115 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableRequest;
116 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
117 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
118 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
119 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
120 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ShutdownRequest;
121 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotRequest;
122 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotResponse;
123 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.StopMasterRequest;
124 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
125 import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
126 import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
127 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
128 import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
129 import org.apache.hadoop.hbase.snapshot.UnknownSnapshotException;
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(sn, 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, sn, 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
1739
1740
1741
1742
1743
1744
1745
1746
1747 public void offline(final byte [] regionName)
1748 throws IOException {
1749 MasterKeepAliveConnection master = connection.getKeepAliveMasterService();
1750 try {
1751 master.offlineRegion(null,RequestConverter.buildOfflineRegionRequest(regionName));
1752 } catch (ServiceException se) {
1753 throw ProtobufUtil.getRemoteException(se);
1754 } finally {
1755 master.close();
1756 }
1757 }
1758
1759
1760
1761
1762
1763
1764
1765 public boolean setBalancerRunning(final boolean on, final boolean synchronous)
1766 throws MasterNotRunningException, ZooKeeperConnectionException {
1767 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1768 try {
1769 SetBalancerRunningRequest req =
1770 RequestConverter.buildSetBalancerRunningRequest(on, synchronous);
1771 return stub.setBalancerRunning(null, req).getPrevBalanceValue();
1772 } catch (ServiceException se) {
1773 IOException ioe = ProtobufUtil.getRemoteException(se);
1774 if (ioe instanceof MasterNotRunningException) {
1775 throw (MasterNotRunningException)ioe;
1776 }
1777 if (ioe instanceof ZooKeeperConnectionException) {
1778 throw (ZooKeeperConnectionException)ioe;
1779 }
1780
1781
1782
1783 throw new MasterNotRunningException("Unexpected exception when calling balanceSwitch",se);
1784 } finally {
1785 stub.close();
1786 }
1787 }
1788
1789
1790
1791
1792
1793
1794
1795 public boolean balancer()
1796 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException {
1797 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1798 try {
1799 return stub.balance(null,RequestConverter.buildBalanceRequest()).getBalancerRan();
1800 } finally {
1801 stub.close();
1802 }
1803 }
1804
1805
1806
1807
1808
1809
1810
1811
1812 public boolean enableCatalogJanitor(boolean enable)
1813 throws ServiceException, MasterNotRunningException {
1814 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1815 try {
1816 return stub.enableCatalogJanitor(null,
1817 RequestConverter.buildEnableCatalogJanitorRequest(enable)).getPrevValue();
1818 } finally {
1819 stub.close();
1820 }
1821 }
1822
1823
1824
1825
1826
1827
1828
1829 public int runCatalogScan() throws ServiceException, MasterNotRunningException {
1830 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1831 try {
1832 return stub.runCatalogScan(null,
1833 RequestConverter.buildCatalogScanRequest()).getScanResult();
1834 } finally {
1835 stub.close();
1836 }
1837 }
1838
1839
1840
1841
1842
1843
1844 public boolean isCatalogJanitorEnabled() throws ServiceException, MasterNotRunningException {
1845 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1846 try {
1847 return stub.isCatalogJanitorEnabled(null,
1848 RequestConverter.buildIsCatalogJanitorEnabledRequest()).getValue();
1849 } finally {
1850 stub.close();
1851 }
1852 }
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862 public void mergeRegions(final byte[] encodedNameOfRegionA,
1863 final byte[] encodedNameOfRegionB, final boolean forcible)
1864 throws IOException {
1865 MasterKeepAliveConnection master = connection
1866 .getKeepAliveMasterService();
1867 try {
1868 DispatchMergingRegionsRequest request = RequestConverter
1869 .buildDispatchMergingRegionsRequest(encodedNameOfRegionA,
1870 encodedNameOfRegionB, forcible);
1871 master.dispatchMergingRegions(null, request);
1872 } catch (ServiceException se) {
1873 IOException ioe = ProtobufUtil.getRemoteException(se);
1874 if (ioe instanceof UnknownRegionException) {
1875 throw (UnknownRegionException) ioe;
1876 }
1877 if (ioe instanceof MergeRegionException) {
1878 throw (MergeRegionException) ioe;
1879 }
1880 LOG.error("Unexpected exception: " + se
1881 + " from calling HMaster.dispatchMergingRegions");
1882 } catch (DeserializationException de) {
1883 LOG.error("Could not parse destination server name: " + de);
1884 } finally {
1885 master.close();
1886 }
1887 }
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897 public void split(final String tableNameOrRegionName)
1898 throws IOException, InterruptedException {
1899 split(Bytes.toBytes(tableNameOrRegionName));
1900 }
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910 public void split(final byte[] tableNameOrRegionName)
1911 throws IOException, InterruptedException {
1912 split(tableNameOrRegionName, null);
1913 }
1914
1915 public void split(final String tableNameOrRegionName,
1916 final String splitPoint) throws IOException, InterruptedException {
1917 split(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(splitPoint));
1918 }
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929 public void split(final byte[] tableNameOrRegionName,
1930 final byte [] splitPoint) throws IOException, InterruptedException {
1931 CatalogTracker ct = getCatalogTracker();
1932 try {
1933 Pair<HRegionInfo, ServerName> regionServerPair
1934 = getRegion(tableNameOrRegionName, ct);
1935 if (regionServerPair != null) {
1936 if (regionServerPair.getSecond() == null) {
1937 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1938 } else {
1939 split(regionServerPair.getSecond(), regionServerPair.getFirst(), splitPoint);
1940 }
1941 } else {
1942 final TableName tableName =
1943 checkTableExists(TableName.valueOf(tableNameOrRegionName), ct);
1944 List<Pair<HRegionInfo, ServerName>> pairs =
1945 MetaReader.getTableRegionsAndLocations(ct,
1946 tableName);
1947 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1948
1949 if (pair.getSecond() == null) continue;
1950 HRegionInfo r = pair.getFirst();
1951
1952 if (r.isSplitParent()) continue;
1953
1954 if (splitPoint != null && !r.containsRow(splitPoint)) continue;
1955
1956 split(pair.getSecond(), pair.getFirst(), splitPoint);
1957 }
1958 }
1959 } finally {
1960 cleanupCatalogTracker(ct);
1961 }
1962 }
1963
1964 private void split(final ServerName sn, final HRegionInfo hri,
1965 byte[] splitPoint) throws IOException {
1966 if (hri.getStartKey() != null && splitPoint != null &&
1967 Bytes.compareTo(hri.getStartKey(), splitPoint) == 0) {
1968 throw new IOException("should not give a splitkey which equals to startkey!");
1969 }
1970 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1971 ProtobufUtil.split(admin, hri, splitPoint);
1972 }
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983 public void modifyTable(final TableName tableName, final HTableDescriptor htd)
1984 throws IOException {
1985 if (!tableName.equals(htd.getTableName())) {
1986 throw new IllegalArgumentException("the specified table name '" + tableName +
1987 "' doesn't match with the HTD one: " + htd.getTableName());
1988 }
1989
1990 executeCallable(new MasterCallable<Void>(getConnection()) {
1991 @Override
1992 public Void call() throws ServiceException {
1993 ModifyTableRequest request = RequestConverter.buildModifyTableRequest(tableName, htd);
1994 master.modifyTable(null, request);
1995 return null;
1996 }
1997 });
1998 }
1999
2000 public void modifyTable(final byte[] tableName, final HTableDescriptor htd)
2001 throws IOException {
2002 modifyTable(TableName.valueOf(tableName), htd);
2003 }
2004
2005 public void modifyTable(final String tableName, final HTableDescriptor htd)
2006 throws IOException {
2007 modifyTable(TableName.valueOf(tableName), htd);
2008 }
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019 Pair<HRegionInfo, ServerName> getRegion(final byte[] tableNameOrRegionName,
2020 final CatalogTracker ct) throws IOException {
2021 if (tableNameOrRegionName == null) {
2022 throw new IllegalArgumentException("Pass a table name or region name");
2023 }
2024 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, tableNameOrRegionName);
2025 if (pair == null) {
2026 final AtomicReference<Pair<HRegionInfo, ServerName>> result =
2027 new AtomicReference<Pair<HRegionInfo, ServerName>>(null);
2028 final String encodedName = Bytes.toString(tableNameOrRegionName);
2029 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
2030 @Override
2031 public boolean processRow(Result data) throws IOException {
2032 HRegionInfo info = HRegionInfo.getHRegionInfo(data);
2033 if (info == null) {
2034 LOG.warn("No serialized HRegionInfo in " + data);
2035 return true;
2036 }
2037 if (!encodedName.equals(info.getEncodedName())) return true;
2038 ServerName sn = HRegionInfo.getServerName(data);
2039 result.set(new Pair<HRegionInfo, ServerName>(info, sn));
2040 return false;
2041 }
2042 };
2043
2044 MetaScanner.metaScan(conf, connection, visitor, null);
2045 pair = result.get();
2046 }
2047 return pair;
2048 }
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058 private byte[] getRegionName(
2059 final byte[] regionNameOrEncodedRegionName) throws IOException {
2060 if (Bytes.equals(regionNameOrEncodedRegionName,
2061 HRegionInfo.FIRST_META_REGIONINFO.getRegionName())
2062 || Bytes.equals(regionNameOrEncodedRegionName,
2063 HRegionInfo.FIRST_META_REGIONINFO.getEncodedNameAsBytes())) {
2064 return HRegionInfo.FIRST_META_REGIONINFO.getRegionName();
2065 }
2066 CatalogTracker ct = getCatalogTracker();
2067 byte[] tmp = regionNameOrEncodedRegionName;
2068 try {
2069 Pair<HRegionInfo, ServerName> regionServerPair
2070 = getRegion(regionNameOrEncodedRegionName, ct);
2071 if (regionServerPair != null && regionServerPair.getFirst() != null) {
2072 tmp = regionServerPair.getFirst().getRegionName();
2073 }
2074 } finally {
2075 cleanupCatalogTracker(ct);
2076 }
2077 return tmp;
2078 }
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089 private TableName checkTableExists(
2090 final TableName tableName, CatalogTracker ct)
2091 throws IOException {
2092 if (!MetaReader.tableExists(ct, tableName)) {
2093 throw new TableNotFoundException(tableName);
2094 }
2095 return tableName;
2096 }
2097
2098
2099
2100
2101
2102 public synchronized void shutdown() throws IOException {
2103 executeCallable(new MasterCallable<Void>(getConnection()) {
2104 @Override
2105 public Void call() throws ServiceException {
2106 master.shutdown(null,ShutdownRequest.newBuilder().build());
2107 return null;
2108 }
2109 });
2110 }
2111
2112
2113
2114
2115
2116
2117
2118 public synchronized void stopMaster() throws IOException {
2119 executeCallable(new MasterCallable<Void>(getConnection()) {
2120 @Override
2121 public Void call() throws ServiceException {
2122 master.stopMaster(null,StopMasterRequest.newBuilder().build());
2123 return null;
2124 }
2125 });
2126 }
2127
2128
2129
2130
2131
2132
2133
2134 public synchronized void stopRegionServer(final String hostnamePort)
2135 throws IOException {
2136 String hostname = Addressing.parseHostname(hostnamePort);
2137 int port = Addressing.parsePort(hostnamePort);
2138 AdminService.BlockingInterface admin =
2139 this.connection.getAdmin(ServerName.valueOf(hostname, port, 0));
2140 StopServerRequest request = RequestConverter.buildStopServerRequest(
2141 "Called by admin client " + this.connection.toString());
2142 try {
2143 admin.stopServer(null, request);
2144 } catch (ServiceException se) {
2145 throw ProtobufUtil.getRemoteException(se);
2146 }
2147 }
2148
2149
2150
2151
2152
2153
2154 public ClusterStatus getClusterStatus() throws IOException {
2155 return executeCallable(new MasterCallable<ClusterStatus>(getConnection()) {
2156 @Override
2157 public ClusterStatus call() throws ServiceException {
2158 GetClusterStatusRequest req = RequestConverter.buildGetClusterStatusRequest();
2159 return ClusterStatus.convert(master.getClusterStatus(null,req).getClusterStatus());
2160 }
2161 });
2162 }
2163
2164 private HRegionLocation getFirstMetaServerForTable(final TableName tableName)
2165 throws IOException {
2166 return connection.locateRegion(TableName.META_TABLE_NAME,
2167 HRegionInfo.createRegionName(tableName, null, HConstants.NINES, false));
2168 }
2169
2170
2171
2172
2173 public Configuration getConfiguration() {
2174 return this.conf;
2175 }
2176
2177
2178
2179
2180
2181
2182 public void createNamespace(final NamespaceDescriptor descriptor) throws IOException {
2183 executeCallable(new MasterCallable<Void>(getConnection()) {
2184 @Override
2185 public Void call() throws Exception {
2186 master.createNamespace(null,
2187 CreateNamespaceRequest.newBuilder()
2188 .setNamespaceDescriptor(ProtobufUtil
2189 .toProtoNamespaceDescriptor(descriptor)).build());
2190 return null;
2191 }
2192 });
2193 }
2194
2195
2196
2197
2198
2199
2200 public void modifyNamespace(final NamespaceDescriptor descriptor) throws IOException {
2201 executeCallable(new MasterCallable<Void>(getConnection()) {
2202 @Override
2203 public Void call() throws Exception {
2204 master.modifyNamespace(null, ModifyNamespaceRequest.newBuilder().
2205 setNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(descriptor)).build());
2206 return null;
2207 }
2208 });
2209 }
2210
2211
2212
2213
2214
2215
2216 public void deleteNamespace(final String name) throws IOException {
2217 executeCallable(new MasterCallable<Void>(getConnection()) {
2218 @Override
2219 public Void call() throws Exception {
2220 master.deleteNamespace(null, DeleteNamespaceRequest.newBuilder().
2221 setNamespaceName(name).build());
2222 return null;
2223 }
2224 });
2225 }
2226
2227
2228
2229
2230
2231
2232
2233 public NamespaceDescriptor getNamespaceDescriptor(final String name) throws IOException {
2234 return
2235 executeCallable(new MasterCallable<NamespaceDescriptor>(getConnection()) {
2236 @Override
2237 public NamespaceDescriptor call() throws Exception {
2238 return ProtobufUtil.toNamespaceDescriptor(
2239 master.getNamespaceDescriptor(null, GetNamespaceDescriptorRequest.newBuilder().
2240 setNamespaceName(name).build()).getNamespaceDescriptor());
2241 }
2242 });
2243 }
2244
2245
2246
2247
2248
2249
2250 public NamespaceDescriptor[] listNamespaceDescriptors() throws IOException {
2251 return
2252 executeCallable(new MasterCallable<NamespaceDescriptor[]>(getConnection()) {
2253 @Override
2254 public NamespaceDescriptor[] call() throws Exception {
2255 List<HBaseProtos.NamespaceDescriptor> list =
2256 master.listNamespaceDescriptors(null, ListNamespaceDescriptorsRequest.newBuilder().
2257 build()).getNamespaceDescriptorList();
2258 NamespaceDescriptor[] res = new NamespaceDescriptor[list.size()];
2259 for(int i = 0; i < list.size(); i++) {
2260 res[i] = ProtobufUtil.toNamespaceDescriptor(list.get(i));
2261 }
2262 return res;
2263 }
2264 });
2265 }
2266
2267
2268
2269
2270
2271
2272
2273 public HTableDescriptor[] listTableDescriptorsByNamespace(final String name) throws IOException {
2274 return
2275 executeCallable(new MasterCallable<HTableDescriptor[]>(getConnection()) {
2276 @Override
2277 public HTableDescriptor[] call() throws Exception {
2278 List<TableSchema> list =
2279 master.listTableDescriptorsByNamespace(null, ListTableDescriptorsByNamespaceRequest.
2280 newBuilder().setNamespaceName(name).build()).getTableSchemaList();
2281 HTableDescriptor[] res = new HTableDescriptor[list.size()];
2282 for(int i=0; i < list.size(); i++) {
2283
2284 res[i] = HTableDescriptor.convert(list.get(i));
2285 }
2286 return res;
2287 }
2288 });
2289 }
2290
2291
2292
2293
2294
2295
2296
2297 public TableName[] listTableNamesByNamespace(final String name) throws IOException {
2298 return
2299 executeCallable(new MasterCallable<TableName[]>(getConnection()) {
2300 @Override
2301 public TableName[] call() throws Exception {
2302 List<HBaseProtos.TableName> tableNames =
2303 master.listTableNamesByNamespace(null, ListTableNamesByNamespaceRequest.
2304 newBuilder().setNamespaceName(name).build())
2305 .getTableNameList();
2306 TableName[] result = new TableName[tableNames.size()];
2307 for (int i = 0; i < tableNames.size(); i++) {
2308 result[i] = ProtobufUtil.toTableName(tableNames.get(i));
2309 }
2310 return result;
2311 }
2312 });
2313 }
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323 public static void checkHBaseAvailable(Configuration conf)
2324 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException, IOException {
2325 Configuration copyOfConf = HBaseConfiguration.create(conf);
2326
2327
2328 copyOfConf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
2329 copyOfConf.setInt("zookeeper.recovery.retry", 0);
2330
2331 HConnectionManager.HConnectionImplementation connection
2332 = (HConnectionManager.HConnectionImplementation)
2333 HConnectionManager.getConnection(copyOfConf);
2334
2335 try {
2336
2337
2338
2339 ZooKeeperKeepAliveConnection zkw = null;
2340 try {
2341 zkw = connection.getKeepAliveZooKeeperWatcher();
2342 zkw.getRecoverableZooKeeper().getZooKeeper().exists(
2343 zkw.baseZNode, false);
2344
2345 } catch (IOException e) {
2346 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2347 } catch (InterruptedException e) {
2348 Thread.currentThread().interrupt();
2349 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2350 } catch (KeeperException e) {
2351 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2352 } finally {
2353 if (zkw != null) {
2354 zkw.close();
2355 }
2356 }
2357
2358
2359 connection.isMasterRunning();
2360
2361 } finally {
2362 connection.close();
2363 }
2364 }
2365
2366
2367
2368
2369
2370
2371
2372
2373 public List<HRegionInfo> getTableRegions(final TableName tableName)
2374 throws IOException {
2375 CatalogTracker ct = getCatalogTracker();
2376 List<HRegionInfo> Regions = null;
2377 try {
2378 Regions = MetaReader.getTableRegions(ct, tableName, true);
2379 } finally {
2380 cleanupCatalogTracker(ct);
2381 }
2382 return Regions;
2383 }
2384
2385 public List<HRegionInfo> getTableRegions(final byte[] tableName)
2386 throws IOException {
2387 return getTableRegions(TableName.valueOf(tableName));
2388 }
2389
2390 @Override
2391 public synchronized void close() throws IOException {
2392 if (cleanupConnectionOnClose && this.connection != null && !this.closed) {
2393 this.connection.close();
2394 this.closed = true;
2395 }
2396 }
2397
2398
2399
2400
2401
2402
2403
2404 public HTableDescriptor[] getTableDescriptorsByTableName(List<TableName> tableNames)
2405 throws IOException {
2406 return this.connection.getHTableDescriptorsByTableName(tableNames);
2407 }
2408
2409
2410
2411
2412
2413
2414
2415 public HTableDescriptor[] getTableDescriptors(List<String> names)
2416 throws IOException {
2417 List<TableName> tableNames = new ArrayList<TableName>(names.size());
2418 for(String name : names) {
2419 tableNames.add(TableName.valueOf(name));
2420 }
2421 return getTableDescriptorsByTableName(tableNames);
2422 }
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437 public synchronized byte[][] rollHLogWriter(String serverName)
2438 throws IOException, FailedLogCloseException {
2439 ServerName sn = ServerName.valueOf(serverName);
2440 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2441 RollWALWriterRequest request = RequestConverter.buildRollWALWriterRequest();
2442 try {
2443 RollWALWriterResponse response = admin.rollWALWriter(null, request);
2444 int regionCount = response.getRegionToFlushCount();
2445 byte[][] regionsToFlush = new byte[regionCount][];
2446 for (int i = 0; i < regionCount; i++) {
2447 ByteString region = response.getRegionToFlush(i);
2448 regionsToFlush[i] = region.toByteArray();
2449 }
2450 return regionsToFlush;
2451 } catch (ServiceException se) {
2452 throw ProtobufUtil.getRemoteException(se);
2453 }
2454 }
2455
2456 public String[] getMasterCoprocessors() {
2457 try {
2458 return getClusterStatus().getMasterCoprocessors();
2459 } catch (IOException e) {
2460 LOG.error("Could not getClusterStatus()",e);
2461 return null;
2462 }
2463 }
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474 public CompactionState getCompactionState(final String tableNameOrRegionName)
2475 throws IOException, InterruptedException {
2476 return getCompactionState(Bytes.toBytes(tableNameOrRegionName));
2477 }
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488 public CompactionState getCompactionState(final byte[] tableNameOrRegionName)
2489 throws IOException, InterruptedException {
2490 CompactionState state = CompactionState.NONE;
2491 CatalogTracker ct = getCatalogTracker();
2492 try {
2493 Pair<HRegionInfo, ServerName> regionServerPair
2494 = getRegion(tableNameOrRegionName, ct);
2495 if (regionServerPair != null) {
2496 if (regionServerPair.getSecond() == null) {
2497 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
2498 } else {
2499 ServerName sn = regionServerPair.getSecond();
2500 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2501 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
2502 regionServerPair.getFirst().getRegionName(), true);
2503 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
2504 return response.getCompactionState();
2505 }
2506 } else {
2507 final TableName tableName =
2508 checkTableExists(TableName.valueOf(tableNameOrRegionName), ct);
2509 List<Pair<HRegionInfo, ServerName>> pairs =
2510 MetaReader.getTableRegionsAndLocations(ct, tableName);
2511 for (Pair<HRegionInfo, ServerName> pair: pairs) {
2512 if (pair.getFirst().isOffline()) continue;
2513 if (pair.getSecond() == null) continue;
2514 try {
2515 ServerName sn = pair.getSecond();
2516 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2517 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
2518 pair.getFirst().getRegionName(), true);
2519 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
2520 switch (response.getCompactionState()) {
2521 case MAJOR_AND_MINOR:
2522 return CompactionState.MAJOR_AND_MINOR;
2523 case MAJOR:
2524 if (state == CompactionState.MINOR) {
2525 return CompactionState.MAJOR_AND_MINOR;
2526 }
2527 state = CompactionState.MAJOR;
2528 break;
2529 case MINOR:
2530 if (state == CompactionState.MAJOR) {
2531 return CompactionState.MAJOR_AND_MINOR;
2532 }
2533 state = CompactionState.MINOR;
2534 break;
2535 case NONE:
2536 default:
2537 }
2538 } catch (NotServingRegionException e) {
2539 if (LOG.isDebugEnabled()) {
2540 LOG.debug("Trying to get compaction state of " +
2541 pair.getFirst() + ": " +
2542 StringUtils.stringifyException(e));
2543 }
2544 } catch (RemoteException e) {
2545 if (e.getMessage().indexOf(NotServingRegionException.class.getName()) >= 0) {
2546 if (LOG.isDebugEnabled()) {
2547 LOG.debug("Trying to get compaction state of " + pair.getFirst() + ": "
2548 + StringUtils.stringifyException(e));
2549 }
2550 } else {
2551 throw e;
2552 }
2553 }
2554 }
2555 }
2556 } catch (ServiceException se) {
2557 throw ProtobufUtil.getRemoteException(se);
2558 } finally {
2559 cleanupCatalogTracker(ct);
2560 }
2561 return state;
2562 }
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580 public void snapshot(final String snapshotName,
2581 final TableName tableName) throws IOException,
2582 SnapshotCreationException, IllegalArgumentException {
2583 snapshot(snapshotName, tableName, SnapshotDescription.Type.FLUSH);
2584 }
2585
2586 public void snapshot(final String snapshotName,
2587 final String tableName) throws IOException,
2588 SnapshotCreationException, IllegalArgumentException {
2589 snapshot(snapshotName, TableName.valueOf(tableName),
2590 SnapshotDescription.Type.FLUSH);
2591 }
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609 public void snapshot(final byte[] snapshotName,
2610 final TableName tableName) throws IOException,
2611 SnapshotCreationException, IllegalArgumentException {
2612 snapshot(Bytes.toString(snapshotName), tableName, SnapshotDescription.Type.FLUSH);
2613 }
2614
2615 public void snapshot(final byte[] snapshotName,
2616 final byte[] tableName) throws IOException,
2617 SnapshotCreationException, IllegalArgumentException {
2618 snapshot(Bytes.toString(snapshotName), TableName.valueOf(tableName),
2619 SnapshotDescription.Type.FLUSH);
2620 }
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640 public void snapshot(final String snapshotName,
2641 final TableName tableName,
2642 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2643 IllegalArgumentException {
2644 SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
2645 builder.setTable(tableName.getNameAsString());
2646 builder.setName(snapshotName);
2647 builder.setType(type);
2648 snapshot(builder.build());
2649 }
2650
2651 public void snapshot(final String snapshotName,
2652 final String tableName,
2653 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2654 IllegalArgumentException {
2655 snapshot(snapshotName, TableName.valueOf(tableName), type);
2656 }
2657
2658 public void snapshot(final String snapshotName,
2659 final byte[] tableName,
2660 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2661 IllegalArgumentException {
2662 snapshot(snapshotName, TableName.valueOf(tableName), type);
2663 }
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686 public void snapshot(SnapshotDescription snapshot) throws IOException, SnapshotCreationException,
2687 IllegalArgumentException {
2688
2689 SnapshotResponse response = takeSnapshotAsync(snapshot);
2690 final IsSnapshotDoneRequest request = IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot)
2691 .build();
2692 IsSnapshotDoneResponse done = null;
2693 long start = EnvironmentEdgeManager.currentTimeMillis();
2694 long max = response.getExpectedTimeout();
2695 long maxPauseTime = max / this.numRetries;
2696 int tries = 0;
2697 LOG.debug("Waiting a max of " + max + " ms for snapshot '" +
2698 ClientSnapshotDescriptionUtils.toString(snapshot) + "'' to complete. (max " +
2699 maxPauseTime + " ms per retry)");
2700 while (tries == 0
2701 || ((EnvironmentEdgeManager.currentTimeMillis() - start) < max && !done.getDone())) {
2702 try {
2703
2704 long sleep = getPauseTime(tries++);
2705 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
2706 LOG.debug("(#" + tries + ") Sleeping: " + sleep +
2707 "ms while waiting for snapshot completion.");
2708 Thread.sleep(sleep);
2709
2710 } catch (InterruptedException e) {
2711 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " to complete");
2712 Thread.currentThread().interrupt();
2713 }
2714 LOG.debug("Getting current status of snapshot from master...");
2715 done = executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection()) {
2716 @Override
2717 public IsSnapshotDoneResponse call() throws ServiceException {
2718 return master.isSnapshotDone(null, request);
2719 }
2720 });
2721 };
2722 if (!done.getDone()) {
2723 throw new SnapshotCreationException("Snapshot '" + snapshot.getName()
2724 + "' wasn't completed in expectedTime:" + max + " ms", snapshot);
2725 }
2726 }
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738 public SnapshotResponse takeSnapshotAsync(SnapshotDescription snapshot) throws IOException,
2739 SnapshotCreationException {
2740 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
2741 final SnapshotRequest request = SnapshotRequest.newBuilder().setSnapshot(snapshot)
2742 .build();
2743
2744 return executeCallable(new MasterCallable<SnapshotResponse>(getConnection()) {
2745 @Override
2746 public SnapshotResponse call() throws ServiceException {
2747 return master.snapshot(null, request);
2748 }
2749 });
2750 }
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772 public boolean isSnapshotFinished(final SnapshotDescription snapshot)
2773 throws IOException, HBaseSnapshotException, UnknownSnapshotException {
2774
2775 return executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection()) {
2776 @Override
2777 public IsSnapshotDoneResponse call() throws ServiceException {
2778 return master.isSnapshotDone(null,
2779 IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot).build());
2780 }
2781 }).getDone();
2782 }
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797 public void restoreSnapshot(final byte[] snapshotName)
2798 throws IOException, RestoreSnapshotException {
2799 restoreSnapshot(Bytes.toString(snapshotName));
2800 }
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815 public void restoreSnapshot(final String snapshotName)
2816 throws IOException, RestoreSnapshotException {
2817 boolean takeFailSafeSnapshot =
2818 conf.getBoolean("hbase.snapshot.restore.take.failsafe.snapshot", false);
2819 restoreSnapshot(snapshotName, takeFailSafeSnapshot);
2820 }
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838 public void restoreSnapshot(final byte[] snapshotName, final boolean takeFailSafeSnapshot)
2839 throws IOException, RestoreSnapshotException {
2840 restoreSnapshot(Bytes.toString(snapshotName), takeFailSafeSnapshot);
2841 }
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859 public void restoreSnapshot(final String snapshotName, boolean takeFailSafeSnapshot)
2860 throws IOException, RestoreSnapshotException {
2861 TableName tableName = null;
2862 for (SnapshotDescription snapshotInfo: listSnapshots()) {
2863 if (snapshotInfo.getName().equals(snapshotName)) {
2864 tableName = TableName.valueOf(snapshotInfo.getTable());
2865 break;
2866 }
2867 }
2868
2869 if (tableName == null) {
2870 throw new RestoreSnapshotException(
2871 "Unable to find the table name for snapshot=" + snapshotName);
2872 }
2873
2874
2875 if (!tableExists(tableName)) {
2876 try {
2877 cloneSnapshot(snapshotName, tableName);
2878 } catch (InterruptedException e) {
2879 throw new InterruptedIOException("Interrupted when restoring a nonexistent table: " +
2880 e.getMessage());
2881 }
2882 return;
2883 }
2884
2885
2886 if (!isTableDisabled(tableName)) {
2887 throw new TableNotDisabledException(tableName);
2888 }
2889
2890
2891 String failSafeSnapshotSnapshotName = null;
2892 if (takeFailSafeSnapshot) {
2893 failSafeSnapshotSnapshotName = conf.get("hbase.snapshot.restore.failsafe.name",
2894 "hbase-failsafe-{snapshot.name}-{restore.timestamp}");
2895 failSafeSnapshotSnapshotName = failSafeSnapshotSnapshotName
2896 .replace("{snapshot.name}", snapshotName)
2897 .replace("{table.name}", tableName.toString().replace(TableName.NAMESPACE_DELIM, '.'))
2898 .replace("{restore.timestamp}", String.valueOf(EnvironmentEdgeManager.currentTimeMillis()));
2899 LOG.info("Taking restore-failsafe snapshot: " + failSafeSnapshotSnapshotName);
2900 snapshot(failSafeSnapshotSnapshotName, tableName);
2901 }
2902
2903 try {
2904
2905 internalRestoreSnapshot(snapshotName, tableName);
2906 } catch (IOException e) {
2907
2908
2909 if (takeFailSafeSnapshot) {
2910 try {
2911 internalRestoreSnapshot(failSafeSnapshotSnapshotName, tableName);
2912 String msg = "Restore snapshot=" + snapshotName +
2913 " failed. Rollback to snapshot=" + failSafeSnapshotSnapshotName + " succeeded.";
2914 LOG.error(msg, e);
2915 throw new RestoreSnapshotException(msg, e);
2916 } catch (IOException ex) {
2917 String msg = "Failed to restore and rollback to snapshot=" + failSafeSnapshotSnapshotName;
2918 LOG.error(msg, ex);
2919 throw new RestoreSnapshotException(msg, e);
2920 }
2921 } else {
2922 throw new RestoreSnapshotException("Failed to restore snapshot=" + snapshotName, e);
2923 }
2924 }
2925
2926
2927 if (takeFailSafeSnapshot) {
2928 try {
2929 LOG.info("Deleting restore-failsafe snapshot: " + failSafeSnapshotSnapshotName);
2930 deleteSnapshot(failSafeSnapshotSnapshotName);
2931 } catch (IOException e) {
2932 LOG.error("Unable to remove the failsafe snapshot: " + failSafeSnapshotSnapshotName, e);
2933 }
2934 }
2935 }
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947 public void cloneSnapshot(final byte[] snapshotName, final byte[] tableName)
2948 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2949 cloneSnapshot(Bytes.toString(snapshotName), TableName.valueOf(tableName));
2950 }
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962 public void cloneSnapshot(final byte[] snapshotName, final TableName tableName)
2963 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2964 cloneSnapshot(Bytes.toString(snapshotName), tableName);
2965 }
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979 public void cloneSnapshot(final String snapshotName, final String tableName)
2980 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2981 cloneSnapshot(snapshotName, TableName.valueOf(tableName));
2982 }
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994 public void cloneSnapshot(final String snapshotName, final TableName tableName)
2995 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2996 if (tableExists(tableName)) {
2997 throw new TableExistsException("Table " + tableName + " already exists");
2998 }
2999 internalRestoreSnapshot(snapshotName, tableName);
3000 waitUntilTableIsEnabled(tableName);
3001 }
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013 private void internalRestoreSnapshot(final String snapshotName, final TableName
3014 tableName)
3015 throws IOException, RestoreSnapshotException {
3016 SnapshotDescription snapshot = SnapshotDescription.newBuilder()
3017 .setName(snapshotName).setTable(tableName.getNameAsString()).build();
3018
3019
3020 internalRestoreSnapshotAsync(snapshot);
3021
3022 final IsRestoreSnapshotDoneRequest request = IsRestoreSnapshotDoneRequest.newBuilder()
3023 .setSnapshot(snapshot).build();
3024 IsRestoreSnapshotDoneResponse done = IsRestoreSnapshotDoneResponse.newBuilder()
3025 .setDone(false).buildPartial();
3026 final long maxPauseTime = 5000;
3027 int tries = 0;
3028 while (!done.getDone()) {
3029 try {
3030
3031 long sleep = getPauseTime(tries++);
3032 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
3033 LOG.debug(tries + ") Sleeping: " + sleep + " ms while we wait for snapshot restore to complete.");
3034 Thread.sleep(sleep);
3035 } catch (InterruptedException e) {
3036 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " restore to complete");
3037 Thread.currentThread().interrupt();
3038 }
3039 LOG.debug("Getting current status of snapshot restore from master...");
3040 done = executeCallable(new MasterCallable<IsRestoreSnapshotDoneResponse>(
3041 getConnection()) {
3042 @Override
3043 public IsRestoreSnapshotDoneResponse call() throws ServiceException {
3044 return master.isRestoreSnapshotDone(null, request);
3045 }
3046 });
3047 }
3048 if (!done.getDone()) {
3049 throw new RestoreSnapshotException("Snapshot '" + snapshot.getName() + "' wasn't restored.");
3050 }
3051 }
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063 private RestoreSnapshotResponse internalRestoreSnapshotAsync(final SnapshotDescription snapshot)
3064 throws IOException, RestoreSnapshotException {
3065 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
3066
3067 final RestoreSnapshotRequest request = RestoreSnapshotRequest.newBuilder().setSnapshot(snapshot)
3068 .build();
3069
3070
3071 return executeCallable(new MasterCallable<RestoreSnapshotResponse>(getConnection()) {
3072 @Override
3073 public RestoreSnapshotResponse call() throws ServiceException {
3074 return master.restoreSnapshot(null, request);
3075 }
3076 });
3077 }
3078
3079
3080
3081
3082
3083
3084 public List<SnapshotDescription> listSnapshots() throws IOException {
3085 return executeCallable(new MasterCallable<List<SnapshotDescription>>(getConnection()) {
3086 @Override
3087 public List<SnapshotDescription> call() throws ServiceException {
3088 return master.getCompletedSnapshots(null, GetCompletedSnapshotsRequest.newBuilder().build())
3089 .getSnapshotsList();
3090 }
3091 });
3092 }
3093
3094
3095
3096
3097
3098
3099
3100
3101 public List<SnapshotDescription> listSnapshots(String regex) throws IOException {
3102 return listSnapshots(Pattern.compile(regex));
3103 }
3104
3105
3106
3107
3108
3109
3110
3111
3112 public List<SnapshotDescription> listSnapshots(Pattern pattern) throws IOException {
3113 List<SnapshotDescription> matched = new LinkedList<SnapshotDescription>();
3114 List<SnapshotDescription> snapshots = listSnapshots();
3115 for (SnapshotDescription snapshot : snapshots) {
3116 if (pattern.matcher(snapshot.getName()).matches()) {
3117 matched.add(snapshot);
3118 }
3119 }
3120 return matched;
3121 }
3122
3123
3124
3125
3126
3127
3128 public void deleteSnapshot(final byte[] snapshotName) throws IOException {
3129 deleteSnapshot(Bytes.toString(snapshotName));
3130 }
3131
3132
3133
3134
3135
3136
3137 public void deleteSnapshot(final String snapshotName) throws IOException {
3138
3139 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(snapshotName));
3140
3141 executeCallable(new MasterCallable<Void>(getConnection()) {
3142 @Override
3143 public Void call() throws ServiceException {
3144 master.deleteSnapshot(null,
3145 DeleteSnapshotRequest.newBuilder().
3146 setSnapshot(SnapshotDescription.newBuilder().setName(snapshotName).build()).build());
3147 return null;
3148 }
3149 });
3150 }
3151
3152
3153
3154
3155
3156
3157 public void deleteSnapshots(final String regex) throws IOException {
3158 deleteSnapshots(Pattern.compile(regex));
3159 }
3160
3161
3162
3163
3164
3165
3166 public void deleteSnapshots(final Pattern pattern) throws IOException {
3167 List<SnapshotDescription> snapshots = listSnapshots(pattern);
3168 for (final SnapshotDescription snapshot : snapshots) {
3169
3170 executeCallable(new MasterCallable<Void>(getConnection()) {
3171 @Override
3172 public Void call() throws ServiceException {
3173 this.master.deleteSnapshot(null,
3174 DeleteSnapshotRequest.newBuilder().setSnapshot(snapshot).build());
3175 return null;
3176 }
3177 });
3178 }
3179 }
3180
3181
3182
3183
3184
3185
3186 abstract static class MasterCallable<V> implements RetryingCallable<V>, Closeable {
3187 protected HConnection connection;
3188 protected MasterKeepAliveConnection master;
3189
3190 public MasterCallable(final HConnection connection) {
3191 this.connection = connection;
3192 }
3193
3194 @Override
3195 public void prepare(boolean reload) throws IOException {
3196 this.master = this.connection.getKeepAliveMasterService();
3197 }
3198
3199 @Override
3200 public void close() throws IOException {
3201
3202 if (this.master != null) this.master.close();
3203 }
3204
3205 @Override
3206 public void throwable(Throwable t, boolean retrying) {
3207 }
3208
3209 @Override
3210 public String getExceptionMessageAdditionalDetail() {
3211 return "";
3212 }
3213
3214 @Override
3215 public long sleep(long pause, int tries) {
3216 return ConnectionUtils.getPauseTime(pause, tries);
3217 }
3218 }
3219
3220 private <V> V executeCallable(MasterCallable<V> callable) throws IOException {
3221 RpcRetryingCaller<V> caller = rpcCallerFactory.newCaller();
3222 try {
3223 return caller.callWithRetries(callable);
3224 } finally {
3225 callable.close();
3226 }
3227 }
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250 public CoprocessorRpcChannel coprocessorService() {
3251 return new MasterCoprocessorRpcChannel(connection);
3252 }
3253 }