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